Project Structure

How the Next.js template is organized.

The template is a Next.js 16 App Router project. Routes live under src/app/[locale], grouped by audience, with API handlers in src/app/api. Everything else (components, config, libraries, i18n, content) sits beside it in src/.

Top-level layout

proxy.ts
source.config.ts

Route groups

Every page is nested under src/app/[locale] so the active locale is available to the whole tree (see Internationalization). Inside it, route groups ((name) folders that don't add a URL segment) split the app by audience and share a layout:

GroupURL prefixContains
(marketing)/Landing, blog, legal, about, contact, AI demo, pay-success
(dashboard)/dashboard, /admin, /setting, /accountAuthenticated app surfaces
(docs)/docsFumadocs-rendered documentation
auth/auth/*Login, register, forgot/reset password, confirm

auth is a plain folder, not a route group, so its pages live at /auth/login, /auth/register, and so on. Only (marketing), (dashboard), and (docs) use the parenthesised group syntax.

Dynamic content lives behind catch-all and dynamic segments: docs render through (docs)/docs/[[...slug]], and blog/legal posts resolve their slugs from MDX in content/.

API routes

Server handlers live in src/app/api, grouped by concern:

RoutePurpose
api/auth/[...all]Better Auth catch-all handler
api/user/{profile,settings,subscription,billing}Authenticated user data
api/admin/usersRole-guarded admin user management
api/payment/{create,query,notify/creem}Creem checkout + signed webhook
api/storage/upload-imageAuthenticated image upload
api/ai/{image,audio,video} (+ /query)Replicate generation + polling
api/chatOpenAI streaming chat (Vercel AI SDK)
api/contactContact form email

Auth, validation, and response shapes are applied per route, not enforced globally — patterns vary between handlers. Read the specific route before relying on a guard. For example, the /admin/users API checks the admin role, but page-level protection in proxy.ts only verifies a session cookie.

Supporting directories

DirectoryRole
src/componentsUI primitives (ui/), feature, layout, and motion components
src/configApp configuration (site, footer, routes, pricing, sidebars)
src/libServer logic: auth, db, email, payment, ai, source, utils
src/i18nnext-intl routing, request, navigation
messagesTranslation catalogs (en.json, zh.json)
contentMDX for docs, blog, and legal pages
publicStatic assets (and runtime uploads/, see Storage)

Request flow: src/proxy.ts

The template uses Next.js 16's proxy.ts (the renamed middleware.ts) for two jobs on every non-API request:

  1. Locale handling — runs next-intl's middleware to detect and prefix the locale.
  2. Protected-path redirect — for /dashboard, /admin, /setting, and /account, it checks for a Better Auth session cookie and redirects to /auth/login?callbackUrl=… when it's missing.
src/proxy.ts
const protectedPaths = ["/dashboard", "/admin", "/setting", "/account"];
// ...
export const config = {
  matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};

The cookie check is a redirect for unauthenticated traffic, not an authorization boundary. It does not validate the session or the user's role — always re-check the session (and role) inside the API route or server component that returns sensitive data.

Content & generated source

Documentation, blog, and legal content are MDX collections defined in source.config.ts (Fumadocs MDX) and loaded through src/lib/source.ts. Fumadocs generates a .source/ directory at build time — it is regenerated from content/, so don't edit it by hand.

Next.js 16 conventions to know

  • Server Components by default. Files are RSC unless they start with "use client". Keep data fetching and secrets on the server.
  • Async request APIs. params, searchParams, headers(), and cookies() are awaited (e.g. const { locale } = await params).
  • React Compiler is enabled, so manual useMemo/useCallback are rarely needed.

On this page