DEV Community

huangyongshan46-a11y
huangyongshan46-a11y

Posted on

The Exact Next.js Project Structure for a SaaS App (2026)

After building multiple SaaS products, this is the file structure that scales from MVP to production.

src/
├── app/
│   ├── (app)/                    # Authenticated pages
│   │   ├── layout.tsx            # Sidebar + nav
│   │   ├── dashboard/page.tsx
│   │   ├── settings/page.tsx
│   │   └── billing/page.tsx
│   ├── (auth)/                   # Auth pages (centered layout)
│   │   ├── login/page.tsx
│   │   └── register/page.tsx
│   ├── (marketing)/              # Public pages
│   │   ├── pricing/page.tsx
│   │   └── blog/page.tsx
│   ├── api/
│   │   ├── auth/[...nextauth]/   # Auth handler
│   │   ├── stripe/               # Billing webhooks
│   │   └── ai/chat/              # AI endpoint
│   ├── layout.tsx                # Root layout
│   └── page.tsx                  # Landing page
├── components/
│   ├── ui/                       # Button, Input, Card, Badge
│   └── ai/                       # Chat interface
├── lib/
│   ├── auth.ts                   # Auth.js v5 config
│   ├── db.ts                     # Prisma singleton
│   ├── stripe.ts                 # Stripe + plans
│   └── utils.ts                  # cn(), helpers
├── prisma/
│   └── schema.prisma
└── types/
    └── next-auth.d.ts
Enter fullscreen mode Exit fullscreen mode

Why route groups

Parenthesized folders (app), (auth), (marketing) share layouts without affecting URLs. Dashboard pages get the sidebar. Auth pages get a centered layout. Marketing pages get the marketing nav. URLs stay clean.

Why lib/ has exactly 4 files

  • auth.ts — single source of truth for auth
  • db.ts — Prisma singleton (prevents connection pool exhaustion in dev)
  • stripe.ts — client + plan definitions
  • utils.ts — cn() and shared helpers

Every page imports from lib/. No duplicated auth or DB logic.

Why components/ui/ stays small

Button, Input, Card, Badge. Four components with variants cover dashboards, settings, billing, and landing pages. Add more when you actually need them.

What NOT to add early

  • middleware.ts — only when you need route-level auth
  • i18n/ — only when you need multiple languages
  • hooks/ — most are premature abstractions

This structure ships as LaunchKit with everything wired up.

GitHub | Get LaunchKit ($49)

Top comments (0)