Next.js Frontend
TurboStack uses Next.js 16 with the App Router for a modern, performant frontend.
Key Features
App Router
File-based routing with layouts and nested routes
Turbopack
Lightning-fast development builds
React 19
Server Components, Actions, and latest features
TypeScript
Full type safety with strict mode
Directory Structure
apps/frontend/
├── app/
│ ├── (marketing)/ # Public pages
│ │ ├── page.tsx # Homepage
│ │ └── pricing/ # Pricing page
│ ├── (auth)/ # Auth pages (no header)
│ │ ├── login/
│ │ ├── register/
│ │ ├── forgot-password/
│ │ └── reset-password/
│ ├── (admin)/ # Protected pages
│ │ ├── dashboard/
│ │ ├── settings/
│ │ └── users/
│ ├── api/ # API routes
│ ├── context/ # React contexts
│ ├── layout.tsx # Root layout
│ └── globals.css # Global styles
├── components/
│ ├── ui/ # shadcn/ui components
│ └── ... # Custom components
├── lib/
│ ├── api.ts # API client
│ └── utils.ts # Utilities
└── hooks/ # Custom React hooks
Route Groups
Route groups organize your pages without affecting the URL structure:
(marketing)
(auth)
(panel)
Public pages with full header and footer./ → Homepage
/pricing → Pricing page
/about → About page
// app/(marketing)/layout.tsx
export default function MarketingLayout({ children }) {
return (
<>
<Header />
<main>{children}</main>
<Footer />
</>
);
}
Authentication pages with minimal layout./login → Login page
/register → Registration
/forgot-password → Password reset request
// app/(auth)/layout.tsx
export default function AuthLayout({ children }) {
return (
<div className="min-h-screen flex items-center justify-center">
{children}
</div>
);
}
Protected pages with sidebar navigation./dashboard → Main dashboard
/settings → User settings
/users → User management (panel)
// app/(panel)/layout.tsx
export default function AdminLayout({ children }) {
return (
<div className="flex">
<Sidebar />
<main className="flex-1">{children}</main>
</div>
);
}
Authentication
Auth Context
The app uses React Context for client-side auth state:
"use client";
import { useAuth } from "@/app/context/auth-context";
export function UserMenu() {
const { user, isLoading, logout } = useAuth();
if (isLoading) return <Skeleton />;
if (!user) return <LoginButton />;
return (
<DropdownMenu>
<DropdownMenuTrigger>
<Avatar src={user.avatar} fallback={user.name} />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => router.push("/settings")}>
Settings
</DropdownMenuItem>
<DropdownMenuItem onClick={logout}>Logout</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
Server-Side Session
Check authentication in Server Components:
// app/(panel)/dashboard/page.tsx
import { getSession } from "@/lib/auth-server";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const session = await getSession();
if (!session) {
redirect("/login");
}
return (
<div>
<h1>Welcome, {session.name}!</h1>
<p>Role: {session.role}</p>
</div>
);
}
Protected Routes
Use the AuthGuard component for client-side protection:
import { AuthGuard } from "@/components/auth-guard";
export default function SettingsPage() {
return (
<AuthGuard requireEmailVerified>
<SettingsForm />
</AuthGuard>
);
}
AuthGuard supports options like requireEmailVerified and allowedRoles= {["ADMIN"]} for fine-grained access control.
Environment Variables
Prefix with NEXT_PUBLIC_ to expose to browser:NEXT_PUBLIC_API_URL=http://localhost:4101
NEXT_PUBLIC_APP_NAME=TurboStack
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Regular env vars are only available on server:JWT_SECRET=your-secret-key
SESSION_SECRET=another-secret
// Only works in Server Components or API routes
const secret = process.env.JWT_SECRET;
Adding New Pages
Create the Page File
// app/(marketing)/features/page.tsx
export default function FeaturesPage() {
return (
<div className="container mx-auto py-12">
<h1 className="text-4xl font-bold">Features</h1>
<p>Discover what TurboStack offers.</p>
</div>
);
}
Add Metadata (Optional)
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Features | TurboStack",
description: "Explore TurboStack features",
};
Update Navigation
Add link to your header/sidebar navigation.
Development
Start Frontend
bash bun run dev:web
Build
bash cd apps/frontend && bun run build
The web app runs on http://localhost:4100.
Use Server Actions for mutations and client-side fetching with useAuth
context for queries to leverage Next.js optimizations.