Getting Started with Next SaaS Starter

So you want to build a SaaS application with Next.js without spending weeks on boilerplate? This guide walks you through everything you need to know about the next-saas-starter template β€” what it is, what it includes, and how to get your development environment up and running.

What is next-saas-starter?

next-saas-starter is a production-ready starter template for building SaaS applications. It bundles together a modern tech stack so you can focus on your product instead of wiring up infrastructure.

Here is what is included out of the box:

  • Next.js 16 with the App Router and React 19
  • TypeScript 5.9 for type safety
  • Tailwind CSS 4 with DaisyUI 5 for theming and pre-built UI components
  • Better Auth for authentication (Google OAuth, magic links)
  • Convex as a real-time backend and database
  • Stripe for payments and subscriptions
  • next-intl for internationalization (English and French)
  • Content Collections with Zod validation for blog posts and pages
  • Vitest with React Testing Library for testing
  • Docker support for containerized deployment

Prerequisites

Before you begin, make sure the following tools are installed on your machine:

  • Node.js 20 or higher β€” Check with node -v
  • npm β€” Comes bundled with Node.js
  • Git β€” For cloning the repository

Optional but recommended:

  • Docker β€” If you plan to use containerized deployment
  • Stripe CLI β€” For testing webhooks locally

Installing Node.js

If you do not have Node.js 20+ installed, the easiest way is to use a version manager:

# Using nvm (macOS/Linux)
nvm install 20
nvm use 20

# Using fnm (cross-platform)
fnm install 20
fnm use 20

You can also download Node.js directly from nodejs.org.

Clone and Install

Clone the repository and install the dependencies:

git clone https://github.com/gosev/next-saas-base.git
cd next-saas-base
npm install

This installs all the dependencies listed in package.json, including Next.js, React, Tailwind CSS, and the rest of the stack.

Environment Setup

Copy the example environment file to create your local configuration:

cp .env.example .env.local

Open .env.local in your editor and fill in the required values:

Required Variables

# Your app URL (use localhost for development)
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Auth secret β€” generate one with: openssl rand -base64 32
AUTH_SECRET=your-generated-secret-here

Authentication (optional)

# Google OAuth
AUTH_GOOGLE_ID=your-google-client-id
AUTH_GOOGLE_SECRET=your-google-client-secret

# Magic link emails via Resend
AUTH_RESEND_KEY=your-resend-api-key

Convex Backend

# These are provided when you link your Convex project
CONVEX_DEPLOYMENT=your-convex-deployment
NEXT_PUBLIC_CONVEX_URL=https://your-project.convex.cloud

Stripe Payments (optional)

STRIPE_TEST_SECRET_KEY=sk_test_...
STRIPE_TEST_WEBHOOK_SECRET=whsec_...
STRIPE_TEST_PRICE_ID=price_...

You do not need every variable configured to start developing. At minimum, set NEXT_PUBLIC_APP_URL and AUTH_SECRET.

Setting Up Convex

This project uses Convex as its backend. To connect your local environment:

npx convex dev

This command will:

  1. Ask you to log in to Convex (or create an account)
  2. Link your local project to a Convex deployment
  3. Sync your database schema
  4. Start watching for changes

Keep this running in a separate terminal while developing.

Start the Development Server

With your environment configured, start the dev server:

npm run dev

Open http://localhost:3000 in your browser. You should see the starter homepage with navigation, a hero section, and the blog.

The dev server uses Turbopack for fast refresh β€” changes you make to your code will appear almost instantly in the browser.

Project Structure

Here is an overview of the key directories:

app/                    # Next.js App Router
β”œβ”€β”€ [locale]/           # Locale-based routing (en, fr)
β”‚   β”œβ”€β”€ (main)/         # Main route group (blog, pages)
β”‚   └── layout.tsx      # Locale layout with next-intl
└── api/                # API routes

components/             # React components (atomic design)
β”œβ”€β”€ ui/                 # Base primitives (buttons, inputs, dialogs)
β”œβ”€β”€ atoms/              # Small reusable components
β”œβ”€β”€ molecules/          # Composed components
β”œβ”€β”€ organisms/          # Large sections (header, footer)
└── providers/          # Context providers

lib/                    # Utilities and core logic
β”œβ”€β”€ auth.ts             # Authentication configuration
β”œβ”€β”€ content/            # Content data layer
β”œβ”€β”€ i18n/               # Internationalization utilities
β”œβ”€β”€ hooks/              # Custom React hooks
β”œβ”€β”€ seo/                # SEO metadata generators
└── utils.ts            # cn() utility for class merging

config/                 # Application configuration
β”œβ”€β”€ site.config.ts      # Site name, URL, description
β”œβ”€β”€ i18n.config.ts      # Supported locales
β”œβ”€β”€ stripe.config.ts    # Stripe plan configuration
β”œβ”€β”€ routes.config.ts    # Route definitions
└── features.config.ts  # Feature flags

content/                # Markdown content (Content Collections)
β”œβ”€β”€ posts/en/           # English blog posts
β”œβ”€β”€ posts/fr/           # French blog posts
└── pages/              # Static pages

messages/               # i18n translation files
β”œβ”€β”€ en.json             # English
└── fr.json             # French

Key Patterns

  • Atomic design: Components are organized from small (atoms/) to large (organisms/)
  • Locale routing: All pages live under app/[locale]/ for automatic language support
  • Server Components: Pages are async server components by default β€” client components use the "use client" directive only when needed
  • Semantic colors: Use DaisyUI colors (primary, secondary, base-100) instead of raw Tailwind colors β€” they adapt to themes automatically

Essential Commands

Here are the commands you will use most often:

# Development
npm run dev              # Start dev server (port 3000)

# Code quality
npm run lint             # Run ESLint
npm run typecheck        # TypeScript type checking
npm test                 # Run tests (single run)
npm run test:watch       # Run tests in watch mode

# Build and production
npm run build            # Production build
npm start                # Start production server

# Full CI pipeline (what runs in GitHub Actions)
npm run ci               # lint + typecheck + test + build

# Full quality check
npm run check:quality    # oxfmt + content + oxlint + typecheck + test + lint + build

Writing and Running Tests

Tests are written with Vitest and React Testing Library. Test files live in the __tests__/ directory.

To run the test suite:

npm test

To run tests in watch mode during development:

npm run test:watch

A basic test looks like this:

import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";

// Mock next-intl for components that use translations
vi.mock("next-intl", () => ({
  useTranslations: () => (key: string) => key,
}));

describe("MyComponent", () => {
  it("renders correctly", () => {
    render(<MyComponent />);
    expect(screen.getByText("expected text")).toBeInTheDocument();
  });
});

Docker Deployment (Optional)

The project includes a multi-stage Dockerfile for production deployment. To build and run with Docker:

# Build the image
docker build -t next-saas-starter .

# Run the container
docker run -p 3000:3000 next-saas-starter

The Docker image uses node:20-alpine and produces a minimal standalone build.

Next Steps

Now that your environment is set up, here are some things to explore:

  1. Customize your site β€” Edit config/site.config.ts to set your app name, URL, and description
  2. Add new pages β€” Create routes under app/[locale]/(main)/
  3. Configure Stripe products β€” Create products in the Stripe Dashboard and add price IDs to your .env.local
  4. Set up Stripe webhooks β€” Use the Stripe CLI for local testing: stripe listen --forward-to localhost:3000/api/stripe/webhook
  5. Write blog content β€” Add markdown files to content/posts/en/ or content/posts/fr/
  6. Add translations β€” Edit messages/en.json and messages/fr.json for new UI strings
  7. Deploy β€” The project works with Vercel, Docker, or any platform that supports Node.js

Happy coding!