Create new

Project Structure

How the codebase is organized and the conventions used throughout.

launch.now follows Next.js App Router conventions with a few additions to keep features self-contained.


Top-level layout

.
├── app/                    Next.js App Router
├── src/
│   ├── components/         Shared UI and feature components
│   ├── lib/                Utilities, config, server helpers
│   └── hooks/              Shared React hooks
├── prisma/
│   └── schema.prisma       Database schema
├── emails/                 React Email templates
├── content/
│   └── docs/               MDX documentation pages
└── public/                 Static assets

app/ — Routes

app/
├── (auth)/                 Auth pages — no layout chrome
│   ├── sign-in/
│   ├── sign-up/
│   ├── forgot-password/
│   └── reset-password/
├── (dashboard)/            App pages — with sidebar layout
│   ├── dashboard/
│   ├── settings/
│   │   ├── profile/
│   │   ├── security/       2FA, passkeys, sessions
│   │   └── billing/
│   └── [orgSlug]/          Org-scoped routes
│       ├── members/
│       └── settings/
├── api/
│   ├── auth/[...all]/      Better Auth handler
│   ├── webhooks/stripe/    Stripe webhook receiver
│   └── trpc/               tRPC router (if enabled)
└── docs/[[...slug]]/       Documentation

Route groups (auth) and (dashboard) let pages share layouts without the group name appearing in the URL.


src/components/ — Components

src/components/
├── ui/                     shadcn/ui primitives (button, input, etc.)
├── features/               Feature-specific components
│   ├── auth/               Sign-in form, sign-up form, etc.
│   │   ├── two-factor/     2FA enable/verify/disable
│   │   └── passkeys/       Add, list, delete passkeys
│   ├── billing/            Pricing, subscription status, portal button
│   ├── organizations/      Create org, member list, invite form
│   └── settings/           Profile, security, notification settings
└── docs/                   Docs-specific components (sidebar, MDX overrides)

The features/ convention keeps all the logic, UI, and types for a feature in one place. When you look for anything billing-related, you look in features/billing/.


src/lib/ — Utilities

src/lib/
├── auth.ts                 Better Auth server config
├── auth-client.ts          Better Auth client helpers
├── prisma.ts               Prisma client singleton
├── stripe.ts               Stripe client singleton
├── resend.ts               Resend client singleton
├── utils.ts                cn() and other shared utilities
└── highlight-code.ts       Shiki syntax highlighting (docs only)

Each external service gets its own file with a singleton client export. Import the client from here everywhere — never instantiate it inline.


prisma/ — Database

prisma/
├── schema.prisma           Full schema including Better Auth tables
└── seed.ts                 Seed script for development data

Better Auth generates its own tables (session, account, verification, etc.) when you run pnpm db:push. Your app models (User extensions, Subscription, Organization, etc.) live in the same schema file.


emails/ — Email templates

emails/
├── reset-password.tsx
├── verify-email.tsx
├── invite-member.tsx
└── _components/            Shared email layout, button, etc.

All templates use React Email. Preview them locally with pnpm email:dev.


Conventions

Barrel exports — each feature folder has an index.ts that re-exports everything. Import from the folder, not from individual files.

// ✓
import { SignInForm } from "@/components/features/auth";

// ✗
import { SignInForm } from "@/components/features/auth/sign-in-form";

Server vs Client — files with database access, auth checks, or env vars are Server Components by default. Add "use client" only when you need interactivity. Keep "use client" as deep in the tree as possible.

Environment variables — server-only vars (no NEXT_PUBLIC_ prefix) are never imported in client components. If you need a value on the client, create a dedicated API route or use a Server Component to pass it as a prop.