Imagine you’re a front-end engineer at a brand-new startup, and you need to decide how to kickstart the product.
Any front-end developer knows that the world of UI is like fast fashion. In my 10-year career so far I’ve re-learned how to create a frontend at least 14 times (off the top of my head):
- Pure HTML, CSS and JS
- Joomla
- WordPress
- Magento 1 with jQuery
- Symfony with Handlebars
- Magento 2 (now Adobe Commerce) with KnockoutJs and RequireJS
- Pure React before the hooks
- Simple Vue.js
- AngularJS
- Laravel with Vue 2 and Vuetify
- Angular 8
- Hugo with AlpineJS
- Next.js with Tailwind and React wih Hooks
- Vue 3 with NuxtJS and Typescript
All of these methods are easy to start, but take a while to perfect.
Different ones fit different types of applications.
And at Smithy we always need to use the best tool for the job :)
In this article I will tell you how we decided what to use.
The constraints
- The Smithy UI is a SaaS or on-prem web application, not a public website.
- The internal pages are not indexed on Google, so we don’t worry about SEO for now.
- The content does not need to be changed by copywriters, so it does not need to have a Content Management System.
- It needs to run in restricted environments, so it has to be simple to deploy.
- It’s changed quickly and iteratively, so it needs to be editable easily.
- It’s a security application, so it has to be as safe as possible, with as few dependencies as possible.
- Our users are highly technical, but may be in stressful roles, so the UI has to be very simple, familiar, intuitive and to the point.
- Experts also expect a quality of software that matches their other tooling, so it has to be fast and has to work on every device.
- Specialists might need to use it while on the train or away, so it has to work well on weak tethered connections.
- It is not a casual tool, so it does not need a mobile app (for now).
- It’s not a media site, so we don’t need large images or videos.
- It is not going to be used for managing accounts, so it does not need to have payments processing or a checkout.
- It needs to be consistent with the Smithy brand, so it needs to support reusable UI libraries and components.
- It needs to be useful for debugging, so it needs to support a socket connection to the server, so users can see what’s going on continuously.
- The whole UI needs to be optional, because power users would use the backend API directly.
- And finally, this is a growing startup, so new employees need to be able to pick it up quickly.
Do we need a framework?
Technically no, but a familiar frontend framework makes some common tasks a
lot easier.
For example:
- Forms and validation
- Graphs and flowcharts
- State, so different part of the UI can maintain consistency
- Routing, so we can get route parameters with no faff
- UI libraries, so we don’t worry about what border the buttons will have
A framework also makes it easier to manage a consistent code style, so new colleagues can hit the ground running. There is a balance though, because it’s very easy to overengineer at this stage. We still want the UI to be as lean as possible, as small as possible, as simple and secure as possible. I am not too worried about the popularity of the framework, because any experienced front-end developer can trivially pick up any of them.
What to use?
We use Go for the backend, because it makes working with Kubernetes a breeze. This rules out any full-stack frameworks like Laravel, Symfony, WordPress, Java Swing etc. In the meantime, our API for the web app is also quite lean, powerful and clean, and needs to work independently of the UI. Thus, the business logic needs to live there. This means we don’t need a framework with full backend for frontend.
When we first began working on Smithy, we wanted something that we could start using immediately, so we could show the power of the product to our customers. We started with Next.js, which is a batteries-included, all-systems-go, full powered battleship. It’s an opinionated React framework that manages routing, modules and rendering. It can do everything, but it also makes it very easy to build unnecessary complexity. For example, when setting it up according to the recommended documentation, we also deployed a backend for frontend, which had to download all node packages at build time (more than 1GB) and set up a separate service to run it on a server alongside the backend’s API. Furthermore, the UI felt slow, and we had issues with unnecessary component re-rendering while typing into forms.
We needed something that’s lighter than a full stack frontend framework, but still modular and easy to update. We could have gone with a statically generated Next.js, but the issue with forms and re-rendering remained. Managing frontend state in React was also turning into an adventure.
So we decided to try something else. We needed to be able to work very quickly, so I did not pick up a framework which I’d never used before (e.g. Svelte or Astro).
I have worked with Vue.js and Angular quite a lot before, so I considered the two. I’ve seen Angular projects that have turned into very complicated conglomerations of piping, services and abstracted design patterns, so I decided that I didn’t want that in my future. And I’ve used Vue.js over and over again on small and large projects, solo, in small teams and in large teams, in startups and in consultancies, and I’ve never seen it get out of hand.
We still needed to make sure we retained all features that we’d already presented to customers, so I went digging to see if that was possible. I had a look at Nuxt.js, which is the Vue equivalent of Next, but seemed slightly more flexible. It turned out that it allows us to use a version of the UI, which is not an SPA, but is split into rendered pages upon build. It also makes it possible to have either a fully-frontend solution, partial server-side hydrated one, or a fully server-side rendered one (as we say at Smithy, ‘Cucumber, Tomato, Feta and olive-oil options’). So it has full support for other methods if we need them in the future.
All the libraries that we were using in our original prototype were available for Vue, so everything seemed easy to convert:
- Forms and validation - Vee Validate
- Graphs and flowcharts in the UI - Vue Flow
- State, so different part of the UI maintain consistency - Pinia
- Routing, so we can get route parameters with no faff - Nuxt router
- UI library - shadcn-vue
- TypeScript support - out of the box
- The Authentication libraries match the ones in NextJS, so we could do a direct conversion there too
I gave myself a week to see if it was feasible to convert the UI from Next.js into NuxtJS. And I actually managed to convert everything within the week! Later we changed the build and deployment setup, so it’s now fully static and served by a simple NGINX server.
The deployment used to need an extra Docker container of more than 1 GB, and took more than 15 minutes to deploy. We cut that to a simple 1.94 MB (456 kB gzip) static bundle that works immediately everywhere.
Any major feature now takes a day to prototype and about a week to build completely. And we can still use all our favourite modules. Vue.js also handles DOM changes differently, so we don’t have strange re-renders anymore.
Vue and Nuxt are open source, so we at Smithy remain true to our dedication to the OSS community by helping with bug reports and fixes. As a bonus, we don’t depend on a large corporation for our systems, and we sleep well at night knowing that the only agenda that the OSS community has is just efficient and useful software.
Just to note, Vue is amazing, but it isn’t for everything. For example, our website/blog is just a statically generated Hugo site, with only CSS, HTML and a tiny amount of AlpineJS. It is deployed immediately on commit and is hosted for free on Cloudflare pages.
I hope that helps you next time you need to decide what tools to use for your UI. If you need any help, I’m always here for you at [email protected]. And if you need to ensure all your UI tooling is on its best behaviour, have a look at our awesome Smithy OSS, or see what we can do for you on https://smithy.security/demo.