Project Structure
Forge favours a flat, predictable layout. Here's what a fresh app template
looks like:
my-app/
├── app/ # Routes (Next.js App Router)
│ ├── (marketing)/ # Public pages
│ ├── (app)/ # Authenticated pages
│ └── api/ # Route handlers
├── components/ # Reusable UI
├── lib/ # Framework-agnostic logic
│ ├── db/ # Drizzle schema + client
│ └── auth/ # Session + OAuth helpers
├── forge.config.ts # Project configuration
└── .env.local # Secrets (git-ignored)The app directory
Routes live here. Forge uses route groups to separate public and authenticated areas without affecting the URL:
import { requireUser } from "@/lib/auth";
export default async function Dashboard() {
const user = await requireUser();
return <h1>Welcome back, {user.name}</h1>;
}requireUser() redirects to /login when there's no session, so protected
pages stay one line.
The lib directory
Anything that isn't a React component goes in lib. Keeping logic out of app
means it's easy to test and easy to reuse.
Rule of thumb
If it imports from react or next, it belongs in components or app.
Everything else belongs in lib.
Path aliases
Forge configures the @/ alias so imports stay clean no matter how deep a file
is nested:
import { db } from "@/lib/db";
import { Button } from "@/components/button";