Introduction to Makerkit Turbo - the leading Next.js Supabase SaaS Starter Kit
Learn how to build and launch your SaaS product quickly using Makerkit Turbo - the leading Next.js Supabase SaaS Starter Kit.
Hi there! 👋 Giancarlo here. I'm the creator of Makerkit.
Welcome to this course on building and launching your SaaS product quickly using Makerkit, the leading Next.js Supabase SaaS Starter Kit. This course will guide you through the process of setting up your SaaS product using Makerkit.
Here is a quick preview of what you will learn:
- Setting up your project: How to set up your project using Makerkit Turbo and Supabase
- Customization: How to customize the design of your app and apply your branding to it 3.Features: How to add new pages and features to your app using Makerkit's architecture
- JS Widget: Building an embeddable Javascript widget and communicate with your app using an external-facing API
- Billing: How to add billing to your app using Stripe and setup your pricing plans and how to handle limits and quotas for your users
- Production: How to deploy your app to production using Vercel
What do we build?
We will be building together a SaaS for Customer Support - a simple helpdesk application that allows users to create tickets and chat with support agents.
This guide can be used as documentation, but it's a more practical approach. For the nitty-gritty details, you can always refer to the official documentation - which should cover everything you need to know.
Makerkit (Turbo version) is built on top of Next.js App Router and Supabase, two powerful tools that make it easy to build and deploy web applications. Next.js is a React framework that provides a great developer experience, while Supabase is an open-source Firebase alternative that provides a powerful backend for your app.
Together, they make a killer tech stack for building ambitious SaaS products - for both large teams and solo developers.
This course will take approximately 8 hours to complete. It's divided into multiple sections, each covering a different aspect of building a SaaS product using Makerkit.
It is highly recommended to follow along using the complete repository at https://github.com/makerkit/next-supabase-saas-kit-turbo-course
. You need a valid license to use the course, you will see a 404 page if you try to access the repository without a valid license.
Let's get started! 🚀
Issues, bugs and feedback
Please use our Discord channel to report any of these. I am striving to make this course as good as possible, and your feedback is invaluable.
What is Makerkit?
Makerkit is a Next.js SaaS Starter Kit that helps you build and launch a SaaS product. Unlike other SaaS kits, Makerkit is opinionated, offers a scalable architecture, and is easily extendable.
The Turbo version is Makerkit's v2, built on top of the learnings and experience gained from the v1, used by thousands of customers every day.
Makerkit Turbo uses Turborepo, a tool that helps you manage multiple packages in a single repository. Turborepo makes it easy to manage the project and add new features - and keeping the codebase clean and organized.
Makerkit resembles a lot a framework that you can use to build your app.
What you'll learn in this course
In this course, you will learn how to build and launch your SaaS product using Makerkit Turbo. Here's what you'll learn:
- Set Up: How to set up your project using Makerkit Turbo
- Customization: How to customize the design of your app
- Supabase: How to use Supabase: migrations, queries, mutations and deploying to production
- Adding Features: How to add new pages and features to your app
- React Query: How to use React Query for efficiently fetching and caching data
- Realtime: How to stream updates from Supabase Realtime to your app
- JS Widget: Building an embeddable Javascript widget and communicate with your app using an external-facing API
- Billing: How to add billing to your app using Stripe and setup your pricing plans
- Deployment: How to deploy your app to production using Vercel
- Troubleshooting: How to troubleshoot common issues and errors, and how to make sure your code is debuggable
- A bit of the basics: Of course, we will also be explaining some of the basics needed to understand the codebase
By the end of this course, you should be able to build most of the features you need for your SaaS product and launch it to production. You'll master Makerkit in no time!
Why Makerkit?
There are countless SaaS starter kits out there, so why should you choose Makerkit? How is it different from the others?
Here are a few reasons:
- Opinionated: Makerkit is opinionated, which means it makes decisions for you. This can be a good thing because it saves you time and helps you avoid common pitfalls.
- Educational: Makerkit is designed to be educational. It's not just a starter kit - it's a learning tool that helps you understand how to build a SaaS product, and understand better Next.js/Remix and Supabase.
- Scalable: Makerkit is built to scale. It's designed to handle large teams and large codebases. It uses Turborepo, a tool that helps you manage multiple packages in a single repository.
- Extendable: Makerkit is easily extendable. You can add new features to your app by creating new packages or apps. You can also customize the design of your app by creating new components or styles.
- Community: Makerkit has a great community. You can ask questions, share your work, and get feedback from other developers using Makerkit.
- Support: I am here to help you get the most from Makerkit. If you have any questions or need help, you can reach out to me on Discord.
Makerkit's Philosophy
Makerkit is built on a few core principles:
Extensibility: You should be able to edit the codebase without fear of breaking things. This means:
- The codebase should be easy to understand - allowing anyone to extend it
- The codebase should be strictly typed - e.g. fail in case of errors, so you can catch them early
- The codebase should be easy to extend - as your app will inevitably diverge from the starter kit
Education: You should be able to learn from the codebase and understand how it works. This means:
- The codebase should be well-documented - so you can understand how it works
- The documentation should inform AND educate - so you can learn how to build your app. This course is a key part of that.
- The documentation should be complete - so you can understand how to use the kit without needing to ask questions
Support: You should be able to get help when you need it. This means:
- The community should be welcoming - so you can ask questions and get help
- The creator should be available - so you can get help when you need it
- The documentation should be up-to-date - so you can get the help you need
Who is this course for?
This course is for developers who want to build and launch a SaaS product quickly and have purchased a license.
This course does not replace the (very extensive) documentation, but it's a more practical and streamlined approach to building a SaaS product.
You should use both in tandem - the official documentation for the details and this course for a more practical, step-by-step guide on building a SaaS product.
What we will build together
In this course, we will be building a SaaS for Customer Support - a simple help-desk application that allows users to create tickets and chat with support agents.
It will have the following features:
- Support Tickets: Users can create support tickets and see updates in real-time.
- Widgets: Users can embed a widget on their website to allow their customers to create tickets.
- Support Agents Chat: Support agents can chat with users in real-time
- Billing: Users can subscribe to a plan and pay using Stripe
- Features Limitations: Users can be limited by the features they can use based on their plan
- A Sprinkle of AI: We will add a sprinkle of AI to the app to make it more interesting - when customers create a ticket, we will use AI to create the name of the ticket based on the content. We can add more AI features as we go.
Prerequisites
Before you start this course, you should have the following:
- Basic knowledge of React, TypeScript, and Tailwind CSS
- Basic knowledge of Next.js App Router
- Basic knowledge of Supabase
- A Makerkit license to access the Makerkit Turbo repository
If you're new to Next.js, Supabase, or Makerkit, I suggest you take a look at the official documentation to get familiar with the tools. You can also check out the Next.js and Supabase documentation to get started. Once you have a good understanding of the tools, you can move on to the next section.
Getting Started
To get started, you will need some software installed on your computer:
- Git
- Node.js (and Pnpm)
- Docker
Docker is needed so we can run Supabase locally. If you don't want to use Docker, you can also use the hosted version of Supabase.
I suggest to install Docker Desktop or Orbstack (a lighter alternative). Please make sure you have Docker installed and running before proceeding, otherwise you will not be able to run the course.
Step 1: Clone the Makerkit Turbo repository
To get started, clone the Makerkit Turbo repository from GitHub:
git clone git@github.com:makerkit/next-supabase-saas-kit-turbo.git
This will create a new directory called next-supabase-saas-kit-turbo
with the project files. Please navigate into the directory:
cd next-supabase-saas-kit-turbo
And now you can install the dependencies. Please install pnpm
if you haven't already:
npm install -g pnpm
And then install the dependencies:
pnpm i
Fantastic! You're now ready to start the project. Please proceed to the next step.
Step 2: Start the project
We now need to start the project. To do this, we need to start the Supabase Docker container and the Next.js development server.
To start the Supabase Docker container, run the following command:
pnpm run supabase:web:start
This will start the Supabase Docker container - and will load the Database migrations and seed data.
Next, we need to start the Next.js development server. To do this, run the following command:
pnpm run dev
This will start the Next.js development server at http://localhost:3000
. You can now open your browser and navigate to this URL to see the project running.
Congratulations! You have successfully started the project. You can now explore the project and start customizing it to your needs. Yay! 🎉
Quick Introduction to Turborepo and PNPM
Turborepo is a monorepo tool that allows you to manage multiple packages in a single repository. It provides a set of commands to manage the packages and dependencies in your project. PNPM is the package manager we use in combination with Turborepo to manage the dependencies and packages in your project.
There's not too much you need to know to use Makerkit effectively, however it's worth taking a moment to understand the basics of Turborepo and PNPM.
Thanks to Turborepo, we can split the codebase into multiple packages (and apps) which allows us to manage the dependencies and packages in a more efficient way, and use incremental builds to speed up the development process (such as, linting, formatting, and type checking).
In fact, Turborepo is able to detect changes that affect the dependencies and packages in your project and cache. For example, try running pnpm run typecheck
: the first time, it will check all the packages. Now, run it again: it will feel instantaneous, as all the packages were cached. However, let's make a change to any package: now, the package and its dependents will be computed again.
PNPM - A faster alternative to NPM
PNPM is a faster alternative to NPM, capable of using less disk space and being faster. It also provides great tooling for working with monorepos.
With PNPM, we can run commands inside apps or packages by using the --filter
argument. This is something you'll be encountering often.
For example, the package @kit/stripe
contains a script called start
, which allows us to start the Stripe CLI.
You can call this command anywhere by specifying the package:
pnpm --filter '@kit/stripe' start
Similarly, you can run commands inside an app by specifying the app:
pnpm --filter web dev
Step 3: Explore the project
Before we start building the project, let's take a moment to explore the project structure - so you can have a high-level understanding of how the project is organized.
Makerkit is organized using Turborepo, a monorepo tool that allows you to manage multiple packages in a single repository.
You can now explore the project. The project is divided into two main parts:
- apps - i.e. the Next.js apps
- packages - shared packages that can be used across multiple apps
The apps
directory contains the Next.js app, while the packages
directory contains the shared packages used by the app.
You can think of the packages
directory as a library of components, hooks, and utilities that can be shared across multiple projects - and it's basically Makerkit-core.
The apps
directory contains the following apps:
web
- the main Next.js appe2e
- the end-to-end tests using Playwright
The packages
directory contains the following packages.
Below are the reusable packages that can be shared across multiple applications (or packages):
- @kit/ui: Shared UI components and styles (using Shadcn UI and some custom components)
- @kit/shared: Shared code and utilities
- @kit/supabase: Supabase package that defines the schema and logic for managing Supabase
- @kit/i18n: Internationalization package that defines utilities for managing translations
- @kit/billing: Billing package that defines the schema and logic for managing subscriptions
- @kit/billing-gateway: Billing gateway package that defines the schema and logic for managing payment gateways
- @kit/email-templates: Here we define the email templates using the react.email package.
- @kit/mailers: Mailer package that abstracts the email service provider (e.g., Resend, Cloudflare, SendGrid, Mailgun, etc.)
- @kit/monitoring: A unified monitoring package that defines the schema and logic for monitoring the application with third party services (e.g., Sentry, Baselime, etc.)
- @kit/database-webhooks: Database webhooks package that defines the actions following database changes (e.g., sending an email, updating a record, etc.)
- @kit/cms: CMS package that defines the schema and logic for managing content
- @kit/next: Next.js specific utilities
And features that can be added to the application:
- @kit/auth: Authentication package (using Supabase)
- @kit/accounts: Package that defines components and logic for managing personal accounts
- @kit/team-accounts: Package that defines components and logic for managing team
- @kit/admin: Admin package that defines the schema and logic for managing users, subscriptions, and more.
- @kit/notifications: Notifications package that defines the schema and logic for managing notifications
And billing packages that can be added to the application:
- @kit/stripe: Stripe package that defines the schema and logic for managing Stripe. This is used by the @kit/billing-gateway package and abstracts the Stripe API.
- @kit/lemon-squeezy: Lemon Squeezy package that defines the schema and logic for managing Lemon Squeezy. This is used by the @kit/billing-gateway package and abstracts the Lemon Squeezy API.
The CMSs that can be added to the application:
- @kit/keystatic: Keystatic package that defines the schema and logic for managing Keystatic. This is used by the @kit/cms package and abstracts the Keystatic API
- @kit/wordpress: WordPress package that defines the schema and logic for managing WordPress. This is used by the @kit/cms package and abstracts the WordPress API.
It's a lot to take in - but don't worry!
We will be exploring these packages in more detail as we build out the project - and generally speaking, you don't need to worry about the packages too much, think of it as a framework that you can use to build your app.
How do apps and packages work together?
Generally speaking, the packages
are the building blocks of the project. They contain the shared logic and utilities that can be used across multiple apps.
Instead, the apps within apps
are the actual applications that use these packages to build the project.
The apps
have two main responsibilities:
- Routing: Define the routes and pages of the application
- Configuration: Define the configuration that is specific to the application (e.g., environment variables, Supabase URL, etc.)
The packages
will receive the configuration from the apps and use it to build the project. This allows you to reuse the packages across multiple apps without having to duplicate the code.
Do I need to worry about the packages?
No, you don't need to worry about the packages too much - and generally speaking you don't need any Turborepo knowledge to build your app with Makerkit. You should think of the packages as a framework that you can use to build your app - just as you would by using any other library or framework.
The packages system is a technical implementation that helps write code decoupled from yours. Think of them as a framework that you can use to build your app. You can use the packages as they are, or you can customize them to fit your needs.
You can even fully ignore packages
and just focus on the apps
- and you will still be able to build your app. Actually - I'd say that's the best way to start.
Just focus on the apps
and build your app - and as you get more comfortable with the project, you can start exploring the packages
and see how they can help you build your app.
Routing Overview
The codebase is structured in a way that makes it easy to navigate and update.
Before we get into the details, I want to refresh your memory on how Next.js App Router's routing system works.
A primer on Next.js routing
Next.js uses a file-system-based routing system - which means we define the route of the application based on the file structure.
Here's how it works:
- Pages: the pages of the applications are defined using the special file convention
page.tsx
. Every file namedpage.tsx
in theapp
directory will be a route in the application. For example,app/home/page.tsx
will be the route/home
. - Layouts: the layouts of the application are defined using the special file convention
_layout.tsx
. Every file namedlayout.tsx
in theapp
directory will be a layout in the application. For example,app/layout.tsx
will be the layout for the entire application. - Pathless routes: whenever a folder is surrounded by parenthesis, it means it's a pathless route. For example,
(marketing)
will be a pathless route in the application. Pathless means thatmarketing
will not be in the URL - it's a route that is not visible in the URL. - Params routes: whenever a folder is surrounded by brackets, it means it's a param route. For example,
[account]
will be a param route in the application. Params routes are dynamic routes that can be used to pass data to the route. - Nested routes: you can nest routes by creating a folder with the same name as the route. For example,
app/home/user/page.tsx
will be the route/home/user
. - Special Conventions: other conventions include loading.tsx for displaying a loading screen and error.tsx for displaying an error screen.
The above is enough for understanding the routing in Makerkit, but for a more complete guide, you can refer to the Next.js documentation.
Routing in Next.js Makerkit Turbo
Here are some of the key files and directories you should be aware of:
- apps-- web--- app--- components--- config--- lib--- content--- styles--- supabase
Diving into apps/web
The apps/web
directory is where the Next.js app lives. Here are some of the key directories and files you should be aware of:
app
- this is where the main app lives. This is where you define the routes of the application.components
- this is where you define the shared components of the application.config
- this is where you define the configuration of the application.lib
- this is where you define the shared libraries of the application.content
- this is where you define the content of the application (by default, uses Keystatic Markdoc files)styles
- this is where you define the styles of the application.supabase
- this is where you define the Supabase configuration, migrations and tests
Diving into app
The app
directory is where the routing of the application is defined. Here are some of the key files you should be aware of:
- app-- home-- (marketing)-- auth-- join-- admin-- update-password-- server-sitemap.xml
The image below shows the routing overview of the application for the directories that will matter the most.
home
- this is where the internal home of the application lives. This is where you define the routes when the user is logged in.(marketing)
- this is where the marketing pages of the application live. This is where you define the routes when the user is not logged in. It's a pathless route, so you don't see it in the URL.auth
- this is where the authentication pages of the application live. This is where you define the routes for the login, signup, and forgot password pages.
Let's break down the directories:
home
- this is where the internal home of the application lives. This is where you define the routes when the user is logged in.(marketing)
- this is where the marketing pages of the application live. This is where you define the routes when the user is not logged in. It's a pathless route, so you don't see it in the URL.auth
- this is where the authentication pages of the application live. This is where you define the routes for the login, signup, and forgot password pages.join
- this is where the join pages of the application live. This route is the route where the user can join a team account following an invitation.admin
- this is where the admin pages of the application live. This is where you define the routes for the super admin pages.update-password
- this is where the update password pages of the application live. This is the route the user is redirected to after resetting their password.server-sitemap.xml
- this is where the sitemap of the application is defined.
Diving into marketing
The marketing
directory is where the marketing pages of the application live. Here are some of the key files you should be aware of:
- (marketing)-- page.tsx <--- home page-- pricing/page.tsx-- faq/page.tsx-- contact/page.tsx-- blog/...-- docs/...-- (legal)/...
Diving into home
The home
directory is where the internal dashboard of the application lives. Here are some of the key files you should be aware of:
- home-- (user)-- [account]
Let's break down the directories:
(user)
- this is where the user pages of the application live. This is where you define the routes for the personal account pages.[account]
- this is where the account pages of the application live. This is where you define the routes for the team account pages.
The home
path allows us to separate the marketing pages from the internal dashboard pages.
So the user home page would be /home/user
and the account home page would be /home/[account]
.
When to use (user)
and [account]
The (user)
and [account]
directories are used to separate the user pages from the account pages. The (user)
directory is used for the personal account pages, while the [account]
directory is used for the team account pages.
Imagine you want to add some settings that are specific to the user - you would add them to the (user)
directory. If you want to add some settings that are specific to the account - you would add them to the [account]
directory.
My SaaS is exclusively B2C, what should I do?
If your app is exclusively B2C, you have the freedom to ignore the [account]
directory and just use the (user)
directory.
What's next?
In this course, we will be building a SaaS product using Makerkit Turbo. We will start by setting up the project, customizing the design, and deploying the app to production.
We will also add new features to the app and explore the different packages that Makerkit Turbo provides.
I hope you're excited to get started! Let's dive in and see you in the next section! 🚀