Project structure

Everything in NextForge has a specific place. Here's the full file tree with each directory and file explained.

Full file tree

nextforge/
├── _variants/                  # Database variant files (deleted after setup)
│   ├── mongodb/                # Mongoose-based auth + OTP logic
│   ├── supabase/               # Supabase-based auth + OTP logic + SQL schema
│   └── firebase/               # Firebase-based auth + OTP logic
│
├── actions/
│   ├── auth.ts                 # loginAction, registerAction, verifyEmailAction, logoutAction
│   └── email.ts                # sendPasswordResetOTPAction, resetPasswordAction, resendVerificationOTPAction
│
├── app/
│   ├── (auth)/
│   │   ├── login/              # /login
│   │   ├── register/           # /register
│   │   ├── verify-email/       # /verify-email
│   │   ├── forgot-password/    # /forgot-password
│   │   └── reset-password/     # /reset-password
│   ├── dashboard/              # /dashboard (protected route)
│   ├── api/auth/[...nextauth]/ # NextAuth handler
│   ├── error.tsx               # Global error boundary
│   ├── not-found.tsx           # 404 page
│   ├── layout.tsx              # Root layout
│   └── globals.css             # Tailwind + CSS variable design tokens
│
├── components/
│   ├── auth/                   # Form components for each auth page
│   ├── nav/                    # Navbar, MobileMenu, NavLinks, ThemeToggle
│   ├── footer/                 # Footer
│   └── ui/                     # Button, Input, Modal, Loader, Toast
│
├── hooks/
│   └── useToast.tsx            # Toast state + provider
│
├── lib/
│   ├── auth.ts                 # NextAuth configuration
│   ├── db/
│   │   ├── mongo.ts            # Mongoose connection (MongoDB variant)
│   │   ├── models/             # User + OTP Mongoose models
│   │   └── supabase.ts         # Supabase client — publishable + secret key helpers (Supabase variant)
│   ├── email.ts                # Resend email templates + sender
│   ├── ratelimit.ts            # Upstash Redis rate limiters
│   ├── sanitize.ts             # XSS escaping + (MongoDB) NoSQL injection stripping
│   ├── tokens.ts               # OTP generation, hashing, verification
│   └── validate.ts             # Zod schemas for all forms
│
├── proxy.ts                    # Next.js 16 middleware (route protection + security headers)
├── setup.mjs                   # Interactive database setup script
└── types/
    ├── index.ts                # ActionState, shared types
    └── next-auth.d.ts          # NextAuth session type extensions

_variants/

Contains the three database backend implementations — MongoDB, Supabase, and Firebase. Each variant is a self-contained set of files: DB client, user model/schema, OTP model/schema, and auth action implementations.

setup.mjsreads this directory, copies the chosen variant's files into the correct locations, removes the unused deps from package.json, and then deletes _variants/ entirely. After setup, this directory does not exist.

actions/

Server actions — functions decorated with 'use server' that handle all form mutations. Two files:

  • auth.ts — loginAction, registerAction, verifyEmailAction, logoutAction
  • email.ts — sendPasswordResetOTPAction, resetPasswordAction, resendVerificationOTPAction

Every action follows the same pipeline: sanitize input → validate with Zod → check rate limit → execute DB operation → return ActionState.

app/

Standard Next.js 16 App Router structure.

  • (auth)/ — route group for all auth pages. The route group wrapper means these pages share no special layout beyond root layout.
  • dashboard/ — the first protected route. Use this as your starting point for authenticated content.
  • api/auth/[...nextauth]/ — NextAuth v5 catch-all route handler.
  • error.tsx — global error boundary. Required to be a client component by Next.js.
  • not-found.tsx — custom 404 page. Server component.
  • layout.tsx — root layout. Wraps everything in SessionProvider and ToastProvider.
  • globals.css — Tailwind v4 @theme{} design token definitions and base resets.

components/

All reusable UI split into four sub-directories:

  • auth/ — form components for each auth page (LoginForm, RegisterForm, etc.)
  • nav/ — Navbar, MobileMenu, NavLinks, ThemeToggle
  • footer/ — Footer component
  • ui/ — primitive components: Button, Input, Modal, Loader, Toast

All components follow the same rule: colors from CSS variables only, no hardcoded values.

hooks/

useToast.tsx — the only custom hook. Provides a React context + useReducer toast system. Export ToastProvider (wraps the app) and useToast() (used in components to fire toasts).

lib/

All non-component, non-action utilities:

  • auth.ts — NextAuth v5 configuration. Credentials + Google providers, JWT callbacks, session callbacks.
  • db/ — database client(s) for the chosen variant, plus Mongoose models.
  • email.ts — Resend client + sendVerificationEmail() and sendPasswordResetEmail() functions.
  • ratelimit.ts — Upstash Redis limiters. authRatelimit (5/min) and otpRatelimit (3/min).
  • sanitize.tsescapeHTML(), sanitizeString(), sanitizeObject(), stripMongoOperators(), sanitizeAndStrip().
  • tokens.tsgenerateOTP(), hashOTP(), verifyOTP(), OTP_EXPIRY_MINUTES.
  • validate.ts — Zod schemas for all forms + parseSchema() helper.

proxy.ts

Next.js 16 middleware — renamed from the legacy middleware.ts. Exports a proxy() function (not middleware()).

Handles two concerns:

  • Route protection — unauthenticated requests to protected routes redirect to /login. Authenticated requests to auth routes (login/register) redirect to /dashboard.
  • Security headers — applied to every response: CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, HSTS (production only).

types/

Two files:

  • index.ts — shared types: User, Session, NavLink, ActionState, OTPPurpose, ToastItem, ButtonVariant, LoaderVariant.
  • next-auth.d.ts — module augmentation that adds id, role, and emailVerified to NextAuth's Session and JWT types.

setup.mjs

The interactive database setup script. Run once after cloning. Written as an ES module (.mjs) so it runs with plain node without TypeScript compilation.

After running, it deletes itself. The final project has no trace of the scaffold setup process.