TurboKit
Frontend

Next.js

Frontend development with Next.js 16

Next.js Frontend

TurboKit uses Next.js 16 with the App Router for the frontend application.

Features

  • App Router - File-based routing with layouts and nested routes
  • Turbopack - Fast development builds
  • React 19 - Latest React features
  • TypeScript - Full type safety

Directory Structure

apps/web/
├── app/
│   ├── layout.tsx      # Root layout
│   ├── page.tsx        # Home page
│   └── globals.css     # Global styles
├── components/
│   └── ui/             # shadcn/ui components
├── lib/
│   └── utils.ts        # Utility functions
├── hooks/              # Custom React hooks
├── components.json     # shadcn/ui config
└── package.json

Development

# Start the web app
bun run dev

The web app runs on http://localhost:4100.

Adding Pages

Create a new file in the app directory:

// app/about/page.tsx
export default function AboutPage() {
  return (
    <div>
      <h1>About</h1>
      <p>Welcome to the about page.</p>
    </div>
  );
}

Environment Variables

Environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser:

NEXT_PUBLIC_API_URL=http://localhost:4101

Access in your components:

const apiUrl = process.env.NEXT_PUBLIC_API_URL;

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, logout } = useAuth();

  if (!user) return null;

  return (
    <div>
      <p>Welcome, {user.name}</p>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

Server-Side Session

Check authentication in Server Components:

// app/dashboard/page.tsx
import { getSession } from "@/lib/session";
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>
    </div>
  );
}

Protected Pages

Use the AuthGuard component:

import { AuthGuard } from "@/components/auth-guard";

export default function ProtectedPage() {
  return (
    <AuthGuard requireEmailVerified={true}>
      <div>Protected content</div>
    </AuthGuard>
  );
}

Tip: Use Server Actions for mutations and API routes for queries to leverage Next.js optimizations.

On this page