🚀 Enterprise Next.js Boilerplate (Antigravity Edition)
FOR AI AGENTS & DEVELOPERS: This documentation is structured to provide deep context, architectural decisions, and operational details to ensure seamless handover to any AI coding assistant (like Antigravity) or human developer.
🧠 Project Context & Architecture (Read Me First)
This is an opinionated, production-ready frontend boilerplate built with Next.js 16 App Router. It is designed to work seamlessly with the companion typescript-boilerplate-be NestJS backend.
🏗️ Core Philosophy
- Type Safety First: Strict TypeScript configuration. DTOs and typed API responses connect frontend to backend.
- App Router Native: Built entirely on Next.js App Router with Server Components and React Server Actions support.
- i18n Native: Localization is baked into routing, API calls, and UI components via
next-intl. - Theme-First Design: Chakra UI v3 with custom theme system for consistent, accessible UI.
- Auth by Default: NextAuth.js integration with JWT token management and automatic session handling.
📐 Architectural Decision Records (ADR)
To understand WHY things are the way they are:
-
Locale-Based Routing:
- Mechanism: All routes are prefixed with locale (e.g.,
/tr/dashboard,/en/login). - Implementation:
next-intlplugin with[locale]dynamic segment inapp/directory. - Config:
localePrefix: 'always'ensures consistent URL structure.
- Mechanism: All routes are prefixed with locale (e.g.,
-
API Client with Auto-Auth & Locale:
- Location:
src/lib/api/create-api-client.ts - Feature: Automatically injects JWT
Authorizationheader from NextAuth session. - Feature: Automatically sets
Accept-Languageheader based on current locale (cookie or URL path). - Auto-Logout: 401 responses trigger automatic signOut and redirect.
- Location:
-
Backend Proxy (CORS Solution):
- Problem: Local development CORS issues when frontend (port 3001) calls backend (port 3000).
- Solution: Next.js
rewritesinnext.config.tsproxies/api/backend/*→http://localhost:3000/api/*. - Usage: API clients use
/api/backend/...paths in development.
-
Provider Composition:
- Location:
src/components/ui/provider.tsx - Stack:
SessionProvider(NextAuth) →ChakraProvider(UI) →ColorModeProvider(Dark/Light) →Toaster(Notifications) - Why: Single import in layout provides all necessary contexts.
- Location:
🚀 Quick Start for AI & Humans
1. Prerequisites
- Node.js: v20.19+ (LTS)
- Package Manager:
npm(Lockfile:package-lock.json) - Backend: Companion NestJS backend running on port 3000 (see
typescript-boilerplate-be)
2. Environment Setup
cp .env.example .env.local
# Edit .env.local with your configuration
Required Environment Variables:
| Variable | Description | Example |
|---|---|---|
NEXTAUTH_URL |
NextAuth callback URL | http://localhost:3001 |
NEXTAUTH_SECRET |
Authentication secret (generate with openssl rand -base64 32) |
abc123... |
NEXT_PUBLIC_API_URL |
Backend API base URL | http://localhost:3001/api |
NEXT_PUBLIC_AUTH_REQUIRED |
Require login for all pages | true or false |
3. Installation & Running
# Install dependencies
npm ci
# Development Mode (HTTPS enabled, port 3001)
npm run dev
# Production Build
npm run build
npm run start
Note: Dev server runs on port 3001 with experimental HTTPS for secure cookie handling.
🌍 Internationalization (i18n) Guide
Deep integration with next-intl provides locale-aware routing and translations.
Configuration
- Supported Locales:
['en', 'tr'] - Default Locale:
tr - Locale Detection: Cookie (
NEXT_LOCALE) → URL path → Default
File Structure
messages/
├── en.json # English translations
└── tr.json # Turkish translations
src/i18n/
├── routing.ts # Locale routing configuration
├── navigation.ts # Typed navigation helpers (Link, useRouter)
└── request.ts # Server-side i18n setup
Usage in Components
// Client Component
"use client";
import { useTranslations } from "next-intl";
export function MyComponent() {
const t = useTranslations("common");
return <h1>{t("welcome")}</h1>;
}
// Navigation with Locale
import { Link } from "@/i18n/navigation";
<Link href="/dashboard">Dashboard</Link>; // Auto-prefixes with current locale
Adding a New Locale
- Add locale code to
src/i18n/routing.ts:export const locales = ["en", "tr", "de"]; // Add 'de' - Create
messages/de.jsonwith translations. - Update
getLocale()increate-api-client.tsif needed.
🔐 Authentication System
Built on NextAuth.js with JWT strategy for seamless backend integration.
How It Works
- Login: User submits credentials →
/api/auth/[...nextauth]→ Backend validates → JWT returned. - Session: JWT stored in encrypted cookie, accessible via
useSession()hook. - API Calls:
createApiClient()automatically addsAuthorization: Bearer {token}header. - Auto-Refresh: Token refreshed before expiry (managed by NextAuth).
Protected Routes
// Use middleware.ts or check session in layout
import { getServerSession } from "next-auth";
export default async function ProtectedLayout({ children }) {
const session = await getServerSession();
if (!session) redirect("/login");
return <>{children}</>;
}
Auth Mode Toggle
Set NEXT_PUBLIC_AUTH_REQUIRED=true for mandatory authentication across all pages.
🎨 UI System (Chakra UI v3)
Theme Configuration
- Location:
src/theme/theme.ts - Font: Bricolage Grotesque (Google Fonts, variable font)
- Color Mode: Light/Dark with system preference detection
Component Organization
src/components/
├── ui/ # Chakra UI wrapper components
│ ├── provider.tsx # Root provider (Session + Chakra + Theme)
│ ├── color-mode.tsx # Dark/Light mode toggle
│ ├── feedback/ # Toaster, alerts, etc.
│ └── ...
├── layout/ # Page layout components (Header, Sidebar, Footer)
├── auth/ # Authentication forms and guards
└── site/ # Site-specific feature components
Toast Notifications
import { toaster } from "@/components/ui/feedback/toaster";
// Success toast
toaster.success({
title: "Saved!",
description: "Changes saved successfully.",
});
// Error toast
toaster.error({ title: "Error", description: "Something went wrong." });
📡 API Integration (Standard Architecture)
The project follows a strict Service + Hook pattern for API integration to ensure separation of concerns, type safety, and efficient caching.
🏆 Golden Standard Reference: src/lib/api/example
🏗️ Architecture Pattern
For every domain (e.g., auth, users), we strictly follow this 4-layer structure:
| Layer | File | Purpose |
|---|---|---|
| 1. Types | types.ts |
Contract: pure TypeScript interfaces/DTOs matching Backend. |
| 2. Service | service.ts |
Logic: Pure functions calling apiRequest. Independent of React. |
| 3. Hooks | use-hooks.ts |
State: React Query wrappers (useQuery, useMutation) for caching & state. |
| 4. Barrel | index.ts |
Public API: Central export point for the module. |
📝 Implementation Guide
1. Define Service (service.ts)
Uses apiRequest wrapper which handles client selection (auth, core, etc.), base URLs, and error normalization.
// src/lib/api/example/auth/service.ts
import { apiRequest } from "@/lib/api/api-service";
import { LoginDto, AuthResponse } from "./types";
const login = (data: LoginDto) => {
return apiRequest<ApiResponse<AuthResponse>>({
url: "/auth/login",
client: "auth", // Selects the correct axios instance from clientMap
method: "post",
data,
});
};
export const authService = { login };
2. Create Hook (use-hooks.ts)
Wraps service in TanStack Query for loading states, caching, and invalidation.
// src/lib/api/example/auth/use-hooks.ts
import { useMutation } from "@tanstack/react-query";
import { authService } from "./service";
export const AuthQueryKeys = {
all: ["auth"] as const,
};
export function useLogin() {
return useMutation({
mutationFn: (data: LoginDto) => authService.login(data),
});
}
3. Use in Components
Components only interact with the Hooks, never the Service or Axios directly.
import { useLogin } from "@/lib/api/example"; // Import from barrel
export function LoginForm() {
const { mutate, isPending } = useLogin();
const handleSubmit = (data) => {
mutate(data, {
onSuccess: () => console.log("Logged in!"),
});
};
}
📂 System Map (Directory Structure)
src/
├── app/ # Next.js App Router
│ ├── [locale]/ # Locale-prefixed routes
│ │ ├── (auth)/ # Auth pages (login, register)
│ │ ├── (site)/ # Main site pages
│ │ ├── (error)/ # Error pages
│ │ ├── layout.tsx # Root layout with providers
│ │ └── page.tsx # Home page
│ └── api/ # Next.js API routes
│ └── auth/ # NextAuth endpoints
├── components/ # React components
│ ├── ui/ # Chakra UI wrappers & base components
│ ├── layout/ # Layout components (Header, Sidebar)
│ ├── auth/ # Auth-related components
│ └── site/ # Feature-specific components
├── config/ # App configuration
├── hooks/ # Custom React hooks
├── i18n/ # Internationalization setup
├── lib/ # Utilities & services
│ ├── api/ # API clients (organized by module)
│ │ ├── auth/ # Auth API (login, register)
│ │ ├── admin/ # Admin API (roles, users)
│ │ └── create-api-client.ts # Axios factory with interceptors
│ ├── services/ # Business logic services
│ └── utils/ # Helper functions
├── theme/ # Chakra UI theme configuration
├── types/ # TypeScript type definitions
└── proxy.ts # API proxy utilities
messages/ # Translation JSON files
public/ # Static assets
🧪 Testing & Development
Available Scripts
npm run dev # Start dev server (HTTPS, port 3001)
npm run build # Production build
npm run start # Start production server
npm run lint # Run ESLint
Development Tools
- React Compiler: Enabled for automatic optimization.
- Top Loader: Visual loading indicator for route transitions.
- ESLint + Prettier: Consistent code formatting.
🛠️ Troubleshooting (Known Issues)
1. HTTPS Certificate Warnings in Development
- Context: Dev server uses
--experimental-httpsfor secure cookies. - Fix: Accept the self-signed certificate warning in your browser.
2. Backend Connection Refused
- Fix: Ensure NestJS backend is running on port 3000.
- Check: Run
curl http://localhost:3000/api/healthto verify.
3. Session Not Persisting
- Fix: Ensure
NEXTAUTH_SECRETis set and consistent between restarts. - Fix: Check that cookies are not blocked by browser settings.
4. Locale Not Detected
- Context: Default falls back to
trif cookie/URL detection fails. - Fix: Clear
NEXT_LOCALEcookie and refresh.
🔗 Related Projects
- Backend: typescript-boilerplate-be - NestJS backend with Prisma, JWT auth, and i18n.
📃 License
This project is proprietary and confidential.