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:
- Ask you to log in to Convex (or create an account)
- Link your local project to a Convex deployment
- Sync your database schema
- 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:
- Customize your site β Edit
config/site.config.tsto set your app name, URL, and description - Add new pages β Create routes under
app/[locale]/(main)/ - Configure Stripe products β Create products in the Stripe Dashboard and add price IDs to your
.env.local - Set up Stripe webhooks β Use the Stripe CLI for local testing:
stripe listen --forward-to localhost:3000/api/stripe/webhook - Write blog content β Add markdown files to
content/posts/en/orcontent/posts/fr/ - Add translations β Edit
messages/en.jsonandmessages/fr.jsonfor new UI strings - Deploy β The project works with Vercel, Docker, or any platform that supports Node.js
Happy coding!