Next.js Supabase Turbo
/

Learn how to build a SaaS with Next.js and Supabase

Introduction to Makerkit Turbo

Learn how to build and launch your SaaS product quickly using Makerkit Turbo - the leading Next.js Supabase SaaS Starter Kit.

Reading Time: 38 minutes

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. You will learn how to set up your project, customize the design, and deploy your app to production. 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.

Combined - they make a killer tech stack for building ambitious SaaS products - for both large teams and solo developers.

This is an early draft of this course - so some things may not be fully working. Please bear with me. It will be fully completed by the end of July 2024.


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 makerkit/next-supabase-saas-kit-turbo-course.

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.

Makerkit Turbo uses Turborepo, a tool that helps you manage multiple packages in a single repository. This 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Community: Makerkit has a great community. You can ask questions, share your work, and get feedback from other developers using Makerkit.
  6. 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 comprehensive - so you can understand how to use it

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 good) official 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 nitty-gritty 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 helpdesk application that allows users to create tickets and chat with support agents.

It will have the following features:

  1. Support Tickets: Users can create support tickets and see updates in real-time.
  2. Widgets: Users can embed a widget on their website to allow their customers to create tickets.
  3. Support Agents Chat: Support agents can chat with users in real-time
  4. Billing: Users can subscribe to a plan and pay using Stripe
  5. Features Limitations: Users can be limited by the features they can use based on their plan
  6. 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.

Getting Started

To get started, you will need some software installed on your computer:

  1. Git
  2. Node.js (and Pnpm)
  3. 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.

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 on 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! 🎉

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. This makes it easy to manage the project and add new features - and keeping the codebase clean and organized.

You can now explore the project. The project is divided into two main parts:

  • apps
  • packages

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:

  1. web - the main Next.js app
  2. e2e - 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. The apps are the actual applications that use these packages to build the project.

The apps have two main responsibilities:

  1. Define the routes and pages of the application
  2. 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.

The packages system is a technicality that helped me write code decoupled from yours - but you don't need to worry about them too much. 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 routing 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:

  1. Pages: the pages of the applications are defined using the special file convention page.tsx. Every file named page.tsx in the app directory will be a route in the application. For example, app/home/page.tsx will be the route /home.
  2. Layouts: the layouts of the application are defined using the special file convention _layout.tsx. Every file named layout.tsx in the app directory will be a layout in the application. For example, app/layout.tsx will be the layout for the entire application.
  3. 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 that marketing will not be in the URL - it's a route that is not visible in the URL.
  4. 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.
  5. 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.
  6. 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:

  1. app - this is where the main app lives. This is where you define the routes of the application.
  2. components - this is where you define the shared components of the application.
  3. config - this is where you define the configuration of the application.
  4. lib - this is where you define the shared libraries of the application.
  5. content - this is where you define the content of the application (by default, uses Keystatic Markdoc files)
  6. styles - this is where you define the styles of the application.
  7. 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.

  1. home - this is where the internal home of the application lives. This is where you define the routes when the user is logged in.
  2. (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.
  3. 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:

  1. home - this is where the internal home of the application lives. This is where you define the routes when the user is logged in.
  2. (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.
  3. 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.
  4. 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.
  5. admin - this is where the admin pages of the application live. This is where you define the routes for the super admin pages.
  6. 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.
  7. 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:

  1. (user) - this is where the user pages of the application live. This is where you define the routes for the personal account pages.
  2. [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.

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! 🚀