Creative Designs Guru

The Ultimate 2024 Tech Stack for Solo SaaS Developers: Build Smarter, Not Harder

June 18, 2024

Building a SaaS as a solo developer is a challenging task. You have to wear multiple hats and be proficient in various technologies, requiring strategic decisions about your tech stack. This means you need to be a full-stack developer familiar with both frontend and backend.

Choosing the right tech stack is crucial for the best developer experience. In this post, I'll share my Next.js stack for building a SaaS and break down the different parts of the stack. I'll also share the favorite tools I rely on. If you want to see the final result, you can check out a live demo of the stack.

Next.js Boilerplate SaaS Dashboard

Hope this post will inspire you and help you on your own SaaS journey.

Next.js, the Backbone of the Stack

As a solo developer, you need a framework that allows you to build full-stack applications with ease. Next.js is an excellent choice for building a SaaS, as it's a React framework that enables you to build modern applications efficiently.

Next.js React Meta framework

I use Next.js to create both the user dashboard and the marketing site. The frontend is written in React, while the backend uses Next.js Route Handlers. The Route Handlers create a RESTful API, which can be used by React components and other clients, such as mobile applications.

Using the same framework for both the marketing site and the dashboard allows me to reuse components and styles across all parts of the SaaS. This makes the design more consistent and development more efficient. Similarly, having both the frontend and backend rely on Next.js makes it extremely easy to share code between the two.

Only One Language, TypeScript

TypeScript programming language logo

To maximize productivity, I use only a single programming language: TypeScript. Combined with Next.js, TypeScript allows me to write both frontend and backend code within one framework and one language, simplifying the development process and reducing context switching.

Shadcn UI with Tailwind CSS

For the UI, I choose Shadcn UI, a collection of components built on top of Radix UI, which provides unstyled React components. Shadcn UI styles Radix UI components using Tailwind CSS to deliver a beautiful UI for the SaaS. The good news is that I can share these components between the marketing site and the user dashboard seamlessly.

Join my Newsletter for JS Devs
Get helpful content about Full-Stack React development with Next JS and Tailwind CSS. No spam, unsubscribe at any time.

Authentication

Authentication is a crucial part of any SaaS. I use Clerk for authentication, which offers comprehensive features like email/password and social login. These basic features are available in many open-source libraries.

Clerk auth logo

However, if your application requires more advanced features, Clerk is an excellent choice. It can handle multi-factor authentication, user impersonation, multi-session support (one user can connect to multiple accounts), blocking disposable emails, brute-force protection, bot protection, and more.

Clerk also offers a complete UI in React for authentication, which can be customized to match your brand. It saves you the time and effort of developing authentication from scratch. Some of the built-in UIs provided by Clerk include Sign Up, Sign In, Forgot Password, Reset Password, and User Profile.

Clerk Sign up page

Multi-tenancy and Team Management

A robust SaaS should support collaboration within teams or organizations. Clerk provides a comprehensive multi-tenancy and team management system, including a full UI for managing teams and inviting users. This means I don't need to implement backend logic or UI for team management, as Clerk handles everything, including sending invitation emails and allowing users to switch between teams seamlessly.

Clerk Multi-tenancy

Role and Permission

With multi-tenancy, it's important to manage roles and permissions. Clerk allows creating custom roles and permissions, enabling users to assign roles. For example, an Admin has all the privileges within the team, while a Read-Only role can only view the resources. This ensures appropriate access and security.

Clerk Roles and Permissions

Database

I use Drizzle ORM for database management because it's type-safe and integrates seamlessly with TypeScript. With Drizzle, I can define models and relationships directly in TypeScript, eliminating the need for an external schema file. This means you don't have to learn another syntax.

Drizzle ORM

Drizzle also provides Drizzle Kit, a CLI tool that simplifies the migration process. With Drizzle Kit, you can generate a migration folder to seamlessly update your database schema.

Additionally, you have Drizzle Studio for a visual interface to manage your database. Drizzle Studio allows you to view your database schema, run queries, and browse your data.

Drizzle Studio

Stripe

Stripe logo

Stripe handles payments and subscriptions seamlessly. With the Stripe SDK, I can easily integrate payment processing into my Next.js application. Stripe offers a checkout page, to which users can be redirected. This page not only reminds users of the plan they are about to subscribe to, but also the monthly or yearly price. Finally, the users can enter their credit card details and subscribe to the selected plan.

Stripe Checkout SaaS

Once a subscription is made, Stripe will send a webhook event to my REST API endpoint, indicating that the user has subscribed. This allows me to update the user's subscription status in my database.

Stripe offers a self-service portal for your users to manage their subscription. In this portal, users can change their plan, update their payment method, cancel their subscription, and view their invoices.

Stripe Customer Portal

Internationalization (i18n)

Next-Intl logo

To reach a global audience, I use the Next-Intl library to support multiple languages in Next.js. Next-Intl ensures type-safe translations, verifying that the correct translation key is in use. This prevents runtime errors caused by missing or incorrect translations.

Crowdin Logo

To make the translation experience more efficient, I use Crowdin, a localization platform that integrates seamlessly with GitHub. Crowdin allows me to manage translations collaboratively, ensuring that the application is available in the desired languages.

Crowdin editor

Form Management

I use React-Hook-Form combined with Zod for form management and validation. React-Hook-Form simplifies form handling in React, while Zod ensures data validation. The Zod schema can be easily shared between the frontend and the backend to ensure data validity on both sides.

Testing

As a SaaS builder, it's essential to ensure that the application works as expected. Without a team to test my application, I must rely on automated tests. This way, I'm confident that my application won't experience any regression when new features are added.

I use Vitest and React Testing Library for unit testing. Vitest is a test runner that supports TypeScript and ESM out of the box, offering a modern alternative to Jest. Another advantage of Vitest is its official VSCode extension and Vitest UI, which make Vitest even better. And, React Testing Library provides utilities for interacting with React components.

Playwright logo

For end-to-end (E2E) and integration testing, I rely on Playwright. Playwright is a powerful tool that allows you to automate browser interactions, making it ideal for testing the full functionality of your application. With Playwright, I can simulate user interactions across different browsers, ensuring that my app performs consistently. Additionally, Playwright is excellent for testing Next.js Route Handlers, as it can easily send HTTP requests and validate responses.

GitHub Actions

GitHub Actions is a powerful tool that I use for Continuous Integration (CI). It allows me to automate the process of running tests and checks on my code before merging changes to the main branch.

GitHub Actions logo

Whenever I push a new commit or create a pull request, GitHub Actions automatically triggers workflows that I have defined in my repository. These workflows run unit tests with Vitest, executing end-to-end tests with Playwright, and performing linting and code formatting checks. If there is any issue, GitHub Actions will notify me, preventing me from merging faulty code.

Because my code is continuously being tested and validated, it provides a safety net that allows me to focus on building new features. Especially as a solo developer, we need to wear multiple hats and have limited time to manually test every aspect of an application.

Logging

I use Pino, a fast and lightweight logging library for Node.js. Pino provides a simple API to log messages and supports structured logging, making it easy to search and analyze logs. In production, I take logging a step further by sending the logs to Better Stack. Better Stack offers a robust logging platform that allows for real-time log monitoring, alerting, and visualization. By integrating Pino with Better Stack, I ensure that all log data is efficiently captured, stored, and accessible, enabling quick identification and resolution of issues in a live environment.

Error Monitoring

For error monitoring, I use Sentry, which captures errors and exceptions. It provides detailed reports that include stack traces, user context, and other relevant information, making it easier to identify issues.

Sentry error monitoring logo

In local development, I use Spotlight to capture Sentry events, taking advantage of Sentry's telemetry without overwhelming the production instance.

Sentry spotlight local

Environment Variables

T3 Env Zod logo

T3 Env is a library that uses Zod to validate and transform environment variables. This ensures that all environment variables are correctly defined and validated.

Linter and Code Formatter

Maintaining a clean codebase is essential. I use ESLint and Prettier for linting and code formatting. ESLint ensures code quality by enforcing best practices and catching potential errors, while Prettier enforces a consistent coding style. This makes the codebase more readable and maintainable.

I recommend using the Airbnb style guide as the base configuration for ESLint, as it's one of the most popular JavaScript style guides. Additionally, I use eslint-plugin-playwright to ensure my Playwright tests follow best practices and eslint-plugin-tailwind to enforce best practices for Tailwind CSS.

VSCode

VSCode logo

Visual Studio Code (VSCode) is my code editor of choice and has a rich ecosystem of extensions. Here are some of the extensions that I recommend that work well with my tech stack:

  • vscode-eslint, integrates ESLint into VS Code
  • vscode-tailwindcss, provides IntelliSense and syntax highlighting for Tailwind CSS
  • vscode-github-actions, manages GitHub Actions workflows directly in VSCode
  • i18n-ally, supports internationalization, offering translation key management, making it easier to work with multiple languages

Conclusion

In conclusion, building a SaaS as a solo developer can be quite challenging. However, choosing the right tech stack can make the process much easier, allowing you to focus on delivering value to your users. The combination of Next.js, TypeScript, Shadcn UI with Tailwind CSS, Clerk, Drizzle ORM, Stripe, and other tools shared in this article provides a scalable environment for building a SaaS product.

These tools not only simplify the development process but also ensure that your application is secure, performant, and user-friendly. They handle everything from authentication, multi-tenancy, and payment processing to database management, testing, and continuous integration, helping you focus on your business logic and user experience.

If you want to check out the final result, you can find a live demo.

I've created a Next.js SaaS boilerplate, which is a comprehensive starting point for building your own SaaS product using the same tech stack shared in this article.

Next.js SaaS Starter kit

The key to success as a solo developer is to leverage the right tools and technologies. This tech stack is my personal choice based on my experience and requirements. Depending on your project's needs, you might choose different tools. However, the principles remain the same: choose tools that make you productive.

I hope this post has given you some insights and inspiration for your own SaaS journey. Happy coding!