Getting Started
This guide takes you from zero to a running SaaSyBase instance on your machine. You'll install dependencies, set up your local database, and understand where everything lives so you can start building immediately.
What is SaaSyBase?
SaaSyBase is a complete SaaS foundation — not a starter template. It gives you everything a real SaaS product needs out of the box: authentication, subscription billing with four payment providers, a token/credit system, team and organization support, an admin dashboard, email templates, a blog CMS, support tickets, and more.
You don't rebuild this infrastructure — you build on top of it. Your job is to add your product's unique logic. SaaSyBase handles the business plumbing.
Who is it for?
- Professional developers who want a battle-tested architecture with clean abstractions, 500+ unit tests, and production-hardened patterns.
- AI-assisted builders (using Cursor, Lovable, Windsurf, etc.) who want a working SaaS backend they can scaffold their app into without building billing, auth, and admin from scratch.
Prerequisites
You need Node.js ^20.19.0, ^22.12.0, or >=24.0.0 and npminstalled on your machine. That's the full runtime requirement. For the shared repo path, you should also have a PostgreSQL database ready before running Prisma migrations, because the committed migration history now targets PostgreSQL.
Tip
node --versionin your terminal. If you see a version in one of those supported ranges, you're ready. Node 18 is no longer supported by the current stack. If not, install an updated release from nodejs.org.Installation
Follow these steps in order to get the app running locally:
0. Choose your local database
The normal repo path is PostgreSQL from day one. If you want the least friction while staying on the same migration lane you'll deploy later, use local PostgreSQL or a hosted PostgreSQL database.
| Option | Best for | What to set |
|---|---|---|
| Local PostgreSQL | Recommended local setup on the shared migration lane | DATABASE_URL="postgresql://..." |
| Hosted PostgreSQL | Cloud development, team sharing, and production parity | DATABASE_URL="postgresql://..." |
| SQLite | Disposable local prototyping only | DATABASE_URL="file:./dev.db" |
Useful starting points:
- Official PostgreSQL downloads
- Official PostgreSQL Docker image
- Neon docs
- Supabase database docs
- Railway PostgreSQL docs
Tip
DATABASE_URL at any PostgreSQL instance you control and stay on that lane for local, staging, and production migrations.Typical local PostgreSQL shape:
DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/DBNAME?schema=public"Note
Warning
dev.db or SQLite migration chain to deploy cleanly later.1. Copy the environment template
cp .env.example .env.localThis creates your local environment file. The template comes pre-configured with sensible defaults — including AUTH_PROVIDER="nextauth" so you can start without any third-party accounts.
Note
ALLOWED_DEV_ORIGINS empty unless you open the dev server through a custom local hostname or tunnel instead of plain http://localhost:3000. If you do use a custom host, add it as a comma-separated list and restart npm run dev.2. Install dependencies
npm install3. Apply existing database migrations
npm run prisma:deployThis reads env values through prisma.config.ts, so the Prisma CLI picks up your local .env.local automatically. It then creates or updates your local database from DATABASE_URL and applies the existing migration history.
In this repo, that existing migration history is PostgreSQL. DATABASE_URLchooses the target database, but it does not switch Prisma's datasource provider, and Prisma 7 does not support provider = env("DATABASE_PROVIDER").
Use npm run prisma:migrate -- --name your-change later only when you intentionally change prisma/schema.prisma and need to generate a new migration. For a fresh install, npm run prisma:deploy is the correct command.
If Prisma reports a failed old migration on a supposedly fresh setup, inspect the resolved DATABASE_URL first. .env.local, other env files, or an enabled secrets provider like Doppler or Infisical can override it and point Prisma at an older database than the one you intended.
Note
npm run prisma:diagnose-providerand confirm both the resolved database URL and the schema provider are PostgreSQL.4. Seed the database
npx prisma db seedThe seed script does more than create the first admin. It also populates the initial catalog and baseline app data, including seeded plans, default settings, and the starter editable site pages the admin UI expects. In an interactive terminal, it prompts you for the admin email and password. For CI or automation, set SEED_ADMIN_PASSWORD and optionally SEED_ADMIN_EMAIL as environment variables to skip the prompt.
Warning
SEED_ADMIN_*values, change those credentials immediately before the app is reachable by anyone else.The password must satisfy the shared password policy from lib/password-policy.ts: at least 8 characters, with one uppercase letter, one lowercase letter, and one number. The prompt does not ask for password confirmation, so enter it carefully.
To skip admin creation entirely, run npx prisma db seed -- --skip-admin.
Note
npx prisma db seed is the baseline bootstrap seed. Use it to create the starter admin account, plans, settings, and editable site pages the app expects. It is different from npm run demo:seed, which is only for optional local sample data after the main bootstrap is already done.4b. Optional demo seed for local development
npm run demo:seedRun this only after npx prisma db seed if you want the shipped admin and user dashboards to feel populated during local development. It adds demo users, organizations, subscriptions, payments, support tickets, notifications, visits, logs, and content so long lists and overview panels are easier to evaluate.
This is not a replacement for the normal Prisma seed and it should not be used as production or staging bootstrap data. Think of it as a local sandbox layer on top of the baseline app setup.
5. Start the dev server
npm run devOpen http://localhost:3000 to see the landing page. Sign in at /sign-in with the admin credentials you set during seeding, then visit /admin to explore the admin dashboard.
If you run local development on a custom domain such as https://app.localhost.test or through a tunnel URL, keep your URL env vars aligned with that host and set ALLOWED_DEV_ORIGINS so Next.js can serve dev assets to it.
A useful first stop is /admin/system, which gives you a live snapshot of maintenance mode, file storage, bearer-token readiness, webhook configuration, and email transport status.
Note
dev and build. It checks for required variables and logs warnings for missing optional ones — so you'll get clear feedback if anything is misconfigured.Tip
.env.local on your machine. For staging and production, prefer platform-native encrypted env vars, or use the optional Secrets & Providers bootstrap if your team standardizes on Infisical or Doppler.Warning
DATABASE_URL from that provider if the value is not already present locally. Make sure the resolved target is the PostgreSQL database you actually intend to migrate before running npm run prisma:deploy.Note
Core Scripts
These are the commands you'll use most often when working on or operating the project:
| Command | When to use it |
|---|---|
| npm run dev | Start the local development server |
| npm run dev:turbo | Faster local startup with Turbopack |
| npm run build | Create a production build |
| npm run start | Run the production build locally |
| npm run typecheck | Validate TypeScript before a deploy or PR |
| npm run lint | Run ESLint |
| npm test | Run Vitest unit and integration tests |
| npm run prisma:studio | Open Prisma Studio to browse the database visually |
| npm run prisma:migrate | Create and apply a new PostgreSQL Prisma migration when you change the schema |
| npm run prisma:deploy | Apply the existing PostgreSQL migration history to a fresh or deployed database |
| npm run prisma:diagnose-provider | Print the resolved database target and schema provider before you migrate |
| npm run demo:seed | Add optional demo sample data on top of the normal bootstrap seed for local UI exploration |
| npm run secrets:doctor | Run the provider CLI directly and report the detected output shape before boot |
Note
npm run dev:turbo uses Turbopack for faster cold starts in development. It does not change the production build path. Use it when you want a faster local loop, and fall back to npm run dev if a plugin or edge case behaves differently.For vibecoders
npm install → set a PostgreSQL DATABASE_URL → npm run prisma:diagnose-provider → npm run prisma:deploy → npx prisma db seed → npm run dev. Add npm run demo:seedafter the normal seed only when you want demo sample data for local evaluation. You rarely need the other commands unless you're modifying the database schema or preparing a deployment.Project Structure
Understanding where things live makes it much easier to find your way around — whether you're browsing the code yourself or pointing an AI agent at it.
saasybase/
├── app/ # Next.js pages and API routes
│ ├── admin/ # Admin dashboard pages
│ ├── api/ # API routes (webhooks, checkout, etc.)
│ ├── dashboard/ # User dashboard pages
│ ├── blog/ # Public blog
│ ├── pricing/ # Public pricing page
│ └── layout.tsx # Root layout (theme, auth provider)
├── components/ # React components
│ ├── ui/ # Reusable primitives (Modal, Toast, etc.)
│ ├── admin/ # Admin-specific components
│ ├── dashboard/ # Dashboard-specific components
│ ├── billing/ # Checkout and billing components
│ └── team/ # Team/org management
├── lib/ # Core business logic
│ ├── auth-provider/ # Auth abstraction (Clerk / NextAuth / Better Auth)
│ ├── payment/ # Payment abstraction (4 providers)
│ ├── email.ts # Email sending
│ ├── settings.ts # Admin settings system (50+ keys)
│ └── ... # Tokens, teams, coupons, etc.
├── prisma/
│ ├── schema.prisma # Database schema (25+ models)
│ └── seed.ts # Database seeding script
├── tests/ # 500+ Vitest tests across 140+ files
└── .env.example # Full environment variable templateRoute groups and URLs
The project uses Next.js route groups to keep admin and dashboard layouts isolated without changing the browser URL. If you see folders like (valid)in the file tree, that's a route group — it affects layout nesting but doesn't appear in the URL.
The name (valid) is a repo convention, not a special Next.js keyword. It simply groups routes that sit inside the main authenticated app shell. You can rename a route-group folder without changing the public URL, as long as the surrounding imports and layouts still line up.
| File path | Browser URL |
|---|---|
| app/admin/(valid)/theme/page.tsx | /admin/theme |
| app/dashboard/(valid)/team/page.tsx | /dashboard/team |
| app/admin/(valid)/system/page.tsx | /admin/system |
| app/admin/(valid)/logs/page.tsx | /admin/logs |
| app/docs/api/page.tsx | /docs/api |
The [...slug] catch-all files under app/admin/ and app/dashboard/ are fallback routes — they handle unmatched paths so the filesystem looks more complex than the actual URL structure.
Where to build your app
Most of your custom product code goes in three places:
app/dashboard/— User-facing pages. Add new pages here for features your users interact with.components/— React components. Use existing UI primitives fromcomponents/ui/before creating new ones.lib/— Business logic. Add your domain logic here, using the existing patterns for database access, validation, and error handling.
For AI-assisted builders
Tech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Auth | Clerk, Better Auth, or NextAuth (Auth.js v5) — switchable via AUTH_PROVIDER |
| Payment | Stripe, Paystack, Paddle, Razorpay — switchable via PAYMENT_PROVIDER |
| Database | Prisma 7 ORM · committed PostgreSQL migration baseline · SQLite only as a separate disposable local lane |
| Styling | Tailwind CSS |
| Rich Text Editor | TipTap (blog posts and editable site pages) |
| Nodemailer (SMTP) or Resend — switchable via EMAIL_PROVIDER | |
| Analytics | Google Analytics 4 (via Data API) + built-in visit tracking |
| PDF Generation | pdf-lib (invoices, refund receipts) |
| Validation | Zod |
| Testing | Vitest (unit/integration) + manual regression checks |
| Monitoring | /api/health endpoint |
Alternative Dev Scripts
| Script | Description |
|---|---|
| npm run dev | Standard dev server (webpack) |
| npm run dev:turbo | Dev server with Turbopack (faster cold starts) |
| npm run dev:full | Dev server + Stripe CLI listener in parallel |
AI Context Files
The repository ships with several AI-facing context files at the repo root. If you use GitHub Copilot, Cursor, Claude Code, Windsurf, or another coding agent, these files are part of the intended workflow.
| File | What it does |
|---|---|
| AGENTS.md | Defines specialized AI agent personas and the areas of the codebase they are expected to understand. |
| ARCHITECTURE.md | Technical design of the multi-provider auth and payment layers. |
| CLAUDE.md | High-value coding rules, architecture notes, quick references, and common pitfalls. |
| CONVENTIONS.md | Coding standards, naming conventions, and file organization rules. |
| INSTRUCTIONS.md | Additional repo guidance and conventions for AI-assisted development. |
| PATTERNS.md | Reusable code patterns for API routes, database queries, and state management. |
| TECH_STACK.md | Comprehensive breakdown of the project dependencies and technical choices. |
Tip
Recommended paths
If you are still choosing your core stack, here are the recommended defaults for most SaaSyBase users:
| Decision | Recommended default | Choose the alternative when |
|---|---|---|
| Database | PostgreSQL from day one | Use SQLite only for throwaway local prototyping that will not share the committed migration history |
| Auth | NextAuth for self-hosted simplicity | Choose Better Auth for stronger self-hosted org support, or Clerk for the fastest managed-auth path |
| Secrets | Platform envs | Choose Infisical or Doppler only when your team already wants a shared secrets platform and CLI workflow |
Tip

