Designing a SaaS in 2023 - Frontend
Our chosen stack is Nuxt 3, which is Vue 3 + Typescript. This is a solid and future-proof tech stack. The project has been around for a while, there's a moderately sized community and several big-name backers. We're also going to use Bulma, but we're not going to use a component library. To find out the reasons behind this decision, read on!
Here are some other libraries off NPM we're going to use with Nuxt:
date-fns - date formatting and manipulation made easy!
auth0/auth0spa-js - we'll need this to facilitate logging in with Auth0
hapi/iron - this will be used to seal/unseal a cookie on the server
jose - used to parse JWKS on the server
pinia-nuxt - global state management on the front-end (goes with pinia below)
numeral - number formatting made easy!
sass - we'll need this to transpile sass into CSS
bulma - this is our CSS framework
And some Nuxt modules:
You may be wondering why we didn't opt to go with Tailwind, Windicss or Unocss. This is where big-picture planning comes into play. We're building a SaaS application to support our main product, which is IoT hardware. This means that our customer is not expected to be spending a lot of time in the UI, if any at all beyond the initial setup. Thus, in the interest of time and developer productivity, Bulma with its ready-styled components, customizability and extensions is the smart way to go. Would I prefer to use Windi? Yes I would. Is it the smart thing to do in this case? It is not.
We chose to go with Auth0, which means we're going to need to use one of their login SDKs. However, rather than communicating with their server every time to validate a token, we're gonna create our encrypted cookie which contains all the information we need to communicate with any APIs we protect with Auth0. Because Nuxt 3 comes with excellent cookie handling infrastructure, this is the easiest, most performant, and very secure way to manage session state for a SaaS application. Libraries used in this process are @hapi/iron, jose and @auth0/auth0-spa-js. We're not going to use Auth0's Vue SDK, because we're not using any functionality contained therein.
To make formatting easier, we'll use date-fns and numeral. These are standard libraries used in thousands of projects. I know numeral has been around for an exceptionally long time, so if anyone has suggestions for a more modern alternative, I'm happy to check them out.
We're also going to use Pinia for state management. Pinia is the spiritual successor to Vuex, Vue's own state management library modeled on React's Redux. Pinia is easy to use, conceptually straightforward forward and does all that Vuex used to do.
Since Nuxt 3 can be used to build both the front-end and middle-tier, it makes sense to hire full-stack engineers to drive the project. It will be more cost-efficient, and work will get done faster. This is the theme of the project -- developer efficiency resulting in quick product to market.
In my experience, the most efficient way to build in Nuxt is by focusing on features rather than problem spaces. For example, if we're building "the like button", the engineer in charge of that is responsible for designing the button itself, hooking it up to the Pinia store, the server API, and the database. This is as opposed to one engineer working on the button front-end code and another on the middle-tier and database. For small to medium-sized projects, separating by problem spaces introduces unnecessary complexity. This is why full-stack engineers are well-paid and highly sought after!
When building out the initial project, I like to start with this process:
Scaffold out start project via CLI
Add all necessary packages
Update any configuration files (tsconfig, nuxtconfig, etc)
Add CSS bindings
Build out starter routes / pages, state store, components, composables
Add a layout if necessary (probably is!)
Once this is all done, feature development can begin. Developers coming in will have a solid foundation to build on, examples of project assets like composables and pages, and most importantly, be able to deploy the code to a publicly available host because it will be secured.
In the next article, we'll tackle backend implementation with microservices and our database of choice - Redis Stack.
Did you find this article valuable?
Support Paul K by becoming a sponsor. Any amount is appreciated!