Read this in Simplified Chinese → docs/开发指南.md
This project is a modern admin template built with Next.js 15, TypeScript, Tailwind CSS v4, and Shadcn UI. It follows a colocation architecture and ships with authentication, themes, navigation, data-table utilities, and middleware so you can develop features quickly.
Update app identity in
src/config/app-config.ts(APP_CONFIG.name,meta.title,meta.description).
- URL: https://main.d3919bjo2q9c5.amplifyapp.com/
- Test account:
linuo - Test password:
Ur8Djfm6vtuf9Lc!
- Node.js: recommended
>= 22; package manager:npmoryarn - Dev server:
npm run devathttp://localhost:3456 - Env vars:
API_BASE_URL(global backend proxy target)- How to set up on first clone: copy
env.exampleto.env.developmentand.env.production, then edit values - Examples: see
env.example; in CI/hosting set env vars in the provider console (e.g., Amplify)
- How to set up on first clone: copy
- Scripts:
npm run dev: start dev server (port3456)npm run build: build artifactsnpm run start: production start (port3456)npm run lint: lint check (ESLint)npm run typecheck: TypeScript type checknpm run format/npm run format:check: Prettier formatnpm run generate:presets: generate theme presets (see “Theme & Preferences”)
src/app: App Router routes and pages(external): external group (e.g., root route redirect)(main)/dashboard/*: dashboard features (recommended place for new features)layout.tsx: root layout wiring theme and preferences
src/components: shared componentsui/: Shadcn UI primitivesdata-table/: table ecosystem (columns, pagination, drag, etc.)layouts/: layout and page-level fragments
src/navigation/sidebar: sidebar menu and role filtering (sidebar-items.ts)src/lib: utilities (auth.ts,utils.ts,theme-utils.ts, etc.)src/stores: Zustand stores (auth/,preferences/)src/server/server-actions.ts: server actions (cookie-based preferences)src/middleware.ts+src/middleware/auth-middleware.ts: route protection (see “Auth & Middleware”)src/styles/presets: theme CSS presets;src/scripts/generate-theme-presets.tsgenerates metadata/typessrc/types/preferences/theme.ts: theme modes and preset types
- App Router + Route Groups:
src/app/(external)/page.tsx: redirect root to/dashboardsrc/app/(main)/dashboard/layout.tsx: dashboard layout and sidebarsrc/app/(main)/dashboard/[...not-found]/page.tsx: not-found fallback
- Redirects:
next.config.mjsredirects/dashboardto/dashboard/default
- Token storage:
- Client:
localStorage(accessToken,refreshToken,user) - Cookie:
auth-token(checked by middleware)
- Client:
- Key APIs (
src/lib/auth.ts):setAuthTokens(tokens): write tolocalStorageandauth-tokencookie, and sync to global auth storelogout(): clear auth and redirect to/auth/v1/login
- Middleware (
src/middleware.ts+src/middleware/auth-middleware.ts):- Protected paths:
/dashboard/:path* - Unauthenticated access → redirect to
/auth/v1/login - Accessing login while authenticated → redirect to
/dashboard - Scope changes: edit
export const config.matcheror the middleware logic
- Protected paths:
- Global proxy:
next.config.mjsrewrites()proxies any non-Next-captured routes toAPI_BASE_URL- Example:
fetch('/api/users')→${API_BASE_URL}/api/users
- Example:
- Recommended wrapper:
src/utils/fetch-with-auth.ts- Adds
Authorization: Bearer <accessToken>automatically - On
401, tries refresh (/api/auth/refresh); on failure clears caches and redirects to login proxyParams: pass-throughtargetPathand realmethodwhen your backend expects a proxy envelope
- Adds
- Usage example:
import React from 'react';
import { useFetchWithAuth } from '@/utils/fetch-with-auth';
export default function Demo() {
const fetchAuth = useFetchWithAuth();
React.useEffect(() => {
fetchAuth('/api/products', { method: 'GET' })
.then(r => r.json())
.then(console.log);
}, [fetchAuth]);
return null;
}- Initial wiring (
src/app/layout.tsx):- Server-side
getPreference('theme_mode'|'theme_preset')reads from cookies - Wraps
PreferencesStoreProvider; useusePreferencesStoreclient-side
- Server-side
- Add a new theme:
- Add a
*.cssinsrc/styles/presets/withlabel:,value:comments and--primaryfor light/dark - Run
npm run generate:presetsto updatesrc/types/preferences/theme.ts - UI pickers will automatically include the new preset
- Add a
- Commit automation (
.husky/pre-commit):- Generates presets and runs Prettier; then executes
lint-staged
- Generates presets and runs Prettier; then executes
- Config file:
src/navigation/sidebar/sidebar-items.tsNavGroup→items: NavMainItem[]- Control visibility using
roles: Role[](seesrc/types/auth.ts) filterMenuByRole(menuGroups, userRole)filters items per current user role
- Dev mode: when
IS_DEVistrue, demo menus (Default/CRM/Finance) are appended
- Create route and page:
mkdir -p src/app/\(main\)/dashboard/products/_components// src/app/(main)/dashboard/products/page.tsx
export default function ProductsPage() {
return (
<div className="space-y-6">
<h1 className="text-2xl font-bold">Products</h1>
<p className="text-muted-foreground">Manage your product information</p>
</div>
);
}- Add sidebar menu:
src/navigation/sidebar/sidebar-items.ts
import { Package } from 'lucide-react';
// Append under the Dashboards group
{
title: 'Products',
url: '/dashboard/products',
icon: Package,
roles: [Role.ADMIN, Role.SUPER_ADMIN],
}-
Private components and table utilities: put
schema.ts,columns.tsx,data-table.tsxin_components/ -
Data access: prefer
fetch-with-auth; useproxyParamsif a proxy envelope is required -
UX and state:
react-hook-form+zodfor forms;zustandfor preferences/light state
- Lint:
npm run lint(CI:npm run lint:ci) - Type check:
npm run typecheck - Formatting:
npm run format/npm run format:check - File naming: kebab-case (see
unicorn/filename-caseineslint.config.mjs) - React rules: avoid unstable nested components, array index keys; memoize context values, etc.
- Build speed:
next.config.mjsskips ESLint/TS during build; runlint+typecheckin CI or locally before deploying
API_BASE_URL: backend base (target forrewrites()); configure via.env.development/.env.production- Dev:
npm run dev→http://localhost:3456 - Build/Run:
npm run build→npm run start
- Copy examples:
cp env.example .env.developmentcp env.example .env.production
- Edit values:
- Dev: set
API_BASE_URLto your dev backend (e.g., API Gateway dev stage likehttps://xxxx.execute-api.<region>.amazonaws.com/dev) - Prod: set
API_BASE_URLto your prod backend (e.g.,https://xxxx.execute-api.<region>.amazonaws.com/prodor custom domain)
- Dev: set
- Optional overrides:
- Use
.env.localfor developer-specific overrides (git-ignored); Next.js loads.env.locallast
- Use
- Notes:
.env.*files are git-ignored (see.gitignore), so they won’t be committed- In hosted environments (e.g., AWS Amplify), set
API_BASE_URLin the environment variables configuration - After setting envs:
npm cithennpm run dev(port3456)
- Menu not visible: ensure you are logged in and the
user.rolehas access (rolesinsidebar-items.ts) - 401 loop: ensure backend implements
/api/auth/refresh; or temporarily disable auto-refresh logic - API 404: check
API_BASE_URL; ensurenext.config.mjsrewrites()is applied - Middleware not working: ensure
src/middleware.tsexists andconfig.matchermatches your routes - Port mismatch: template scripts use port
3456(seepackage.jsondev/start)
- Backend template:
aws-cdk-nestjs-template(NestJS + AWS CDK). Repo: https://github.com/lfhwnqe/aws-cdk-nestjs-template- Matches this frontend in auth (JWT/refresh), path proxying (
/api/*), and env var conventions (API_BASE_URL).
- Matches this frontend in auth (JWT/refresh), path proxying (
- Deployment recommendation (AWS Amplify for frontend): use AWS Amplify Hosting for this Next.js app and deploy the backend with the above template to AWS (API Gateway + Lambda or ECS/Fargate).
- In Amplify console, set
API_BASE_URLto your backend API Gateway domain (or custom domain). - Keep frontend and backend in the same AWS Account/Region to minimize latency and simplify IAM.
- Amplify recognizes Next.js; if needed, use
npm ci && npm run buildto build. - Proxy note: this template's
rewrites()forwards non-Next/api/*requests toAPI_BASE_URL.
- In Amplify console, set
- Quick Start:
docs/快速开始.md - Practical Examples:
docs/实战示例.md - Query/Action Bar:
docs/query-action-bar.md - Style & Contribution:
AGENTS.md