Get Started
Set up Next Starter locally: clone the repo, set environment variables, start PostgreSQL in Docker, run Prisma migrations, and start the Next.js dev server.
Prerequisites
Install these first:
- Node.js 22.22.1 or newer, which is what
package.jsondeclares in itsenginesfield. Next.js 16 itself only asks for 20.9, but Prisma refuses to install on anything below 20.19 or 22.12, and lint-staged, which the pre-commit hook runs, wants 22.22.1. The Docker image runs Node 24. - pnpm. The package manager this template uses.
- Docker. Runs PostgreSQL on your machine through
docker-compose. - Google OAuth credentials. Only social sign-in uses them, but the env schema wants both keys present either way.
1. Clone and install
git clone <your-repo-url> my-app
cd my-app
pnpm install2. Configure environment
Copy the example file to create your local .env.
cp .env.example .env.env.example ships with the app URLs pointed at localhost:3000 and a DATABASE_URL whose user, password, port, and database name match docker-compose.yml. Leave those as they are. Start with the auth secret:
pnpm dlx auth secretPaste the output into BETTER_AUTH_SECRET.
A blank key breaks the page, not just the feature
lib/validations/env.ts calls envSchema.parse(process.env) the moment it loads, and lib/auth.ts imports it. The marketing layout reads the session, so a blank STRIPE_SECRET_KEY or STORAGE_S3_ENDPOINT throws on the homepage, the same as it does on billing or uploads. Search .env.example for ="", skip the commented-out lines, and that's your list of keys to fill.
The schema checks the shape of a value, never whether the credential works. So you can boot the app before signing up for five services: anything that parses as a URL for the two storage URLs, an ID starting with price_ for each Stripe price, 32 characters or more for the auth secret, and any non-empty string for the rest. Swap in real credentials before you touch the feature behind them.
One exception. lib/auth.ts sets requireEmailVerification: true and the code arrives by email, so SMTP2Go has to be real before you can verify your first account and sign in.
For the full variable list, see the Environment Variables reference.
| Service | What it powers | Guide |
|---|---|---|
| Google OAuth | Social sign-in | Authentication |
| Stripe | Subscription billing | Billing |
| SMTP2Go | Transactional email | |
| Cloudflare R2 | File uploads and avatars | File Uploads |
| Cloudflare Turnstile | Bot protection on the contact form | Turnstile |
3. Start the database
PostgreSQL 18 comes up in Docker on port 5432.
docker-compose up -dIt creates a next_starter database with the postgres / postgres credentials that the default DATABASE_URL expects.
4. Run migrations
Two commands. The first creates your tables, the second generates the typed Prisma client.
pnpm prisma migrate dev
pnpm prisma generateThat second command isn't optional. In Prisma 7, migrate dev applies migrations but doesn't generate the client, so without it your code won't know about the new tables. The generated/ folder is gitignored too, so a fresh clone has no client at all until you run it.
To wipe the database and start fresh, run:
docker-compose down -v && docker-compose up -d && pnpm prisma migrate dev && pnpm prisma generate5. Start the dev server
This runs Next.js at http://localhost:3000.
pnpm devThe build script migrates, and Git push runs it
pnpm dev only starts Next.js. The build script runs prisma generate && next build && prisma migrate deploy, so a production deploy applies any pending migrations on its own.
And .husky/pre-push runs pnpm build too, so every git push applies migrations to whatever DATABASE_URL your shell or .env points at. Keep that pointed somewhere local, or drop the hook.
Preview email templates (optional)
The React Email preview runs at http://localhost:3001.
pnpm emailEdit any file in lib/email/ and the preview reloads right away.
What you should see
/ serves the marketing landing page. Register at /auth/register and enter the 6-digit code you receive. That verifies the account, signs you in, and drops you into the onboarding wizard at /onboarding. Finishing the wizard or hitting its skip button unlocks /dashboard.
To make yourself an admin, open the user table and set the role field on your row to "admin".
Next steps
- Set up Stripe to turn on subscription billing
- Skim the project structure to find where things live
- Build a feature with the first SaaS app tutorial
Introduction
Next Starter is a Next.js 16 SaaS boilerplate with Better Auth, Stripe billing, Prisma and PostgreSQL, file storage, email, and an admin dashboard.
Project Structure
A map of the Next Starter directory layout: the folders and key files in this Next.js SaaS kit, plus conventions for where new pages, components, and actions go.