CLI scaffolding tool that generates production-ready SaaS projects on top of Next.js.
npm install -g saas-initOr use directly without installing:
npx saas-init initsaas-init initThe CLI walks you through a short prompt sequence:
- Project name (lowercase, npm-valid, e.g.
my-app) - Output directory (default:
./<project-name>) - Auth provider
- Database
- Payments (optional)
- Email (optional)
- Summary — confirm before any files are written
After confirming, saas-init generates the project files and optionally runs pnpm install in the output directory.
Every generated project comes with:
- Landing Page: Production-ready landing page with multiple sections (hero, problem agitate, value proposition, social proof, transformation, CTA, footer). Fully customizable via template variables.
- Docker: Pre-configured
Dockerfileanddocker-compose.ymlfor easy containerization. - GitHub Actions: Automated CI workflow for testing and linting on every push and PR.
| Category | Options |
|---|---|
| Auth | Clerk, NextAuth, Supabase Auth |
| Database | Postgres (Drizzle), SQLite (Drizzle), Supabase |
| Payments | Stripe, Lemon Squeezy, None |
| Resend, Postmark, None |
-
Add templates under
templates/<category>/<provider>/. Use{{key}}placeholders for variables that come fromProjectConfig. -
Create a generator at
src/generators/<category>/<provider>.tsthat exports:export async function generate(config: ProjectConfig, outDir: string): Promise<void>
Inside it, use the file utilities to copy templates and merge dependencies:
import path from 'path' import fs from 'fs-extra' import { writeTemplate, appendEnv } from '../../utils/files.js' import { mergeDeps } from '../../utils/deps.js' import { TEMPLATES_ROOT } from '../../utils/paths.js' const TEMPLATES_DIR = path.join(TEMPLATES_ROOT, '<category>/<provider>') export async function generate(config: ProjectConfig, outDir: string): Promise<void> { await writeTemplate( path.join(TEMPLATES_DIR, 'lib/client.ts'), path.join(outDir, 'lib/client.ts'), {} ) const pkgPath = path.join(outDir, 'package.json') const pkg = await fs.readJson(pkgPath) pkg.dependencies = mergeDeps(pkg.dependencies ?? {}, { '<package>': '^1.0.0' }) await fs.writeJson(pkgPath, pkg, { spaces: 2 }) await appendEnv(outDir, { MY_API_KEY: '' }) }
-
Register the generator in
src/generators/index.tsby adding it to the relevant map (e.g.authGenerators,databaseGenerators, etc.). -
Add the new value to the relevant union type in
src/types.tsand the matching zod enum inprojectConfigSchema. -
Add a prompt option in
src/prompts/<category>.ts. -
Write tests in
tests/generators/<category>/<provider>.test.tsfollowing the patterns of existing generator tests.
- Node.js >= 18
- pnpm (for generated projects)