# Ant Design Pro — Admin & Architecture Guide

This guide is for the architect, tech lead, or platform engineer deciding whether and how to adopt Ant Design Pro as the foundation for an enterprise web application — and for the developers who will operate, extend, and harden it. It documents the architecture, the complete configuration surface, the request/permission/i18n internals, the demo backend, deployment, security considerations, and the improvements worth making before production.

Where the [User Guide](/guides/ant-design/ant-design-pro/user-guide/) shows you how to *use* the template, this guide explains *how it is built and how to make it production-grade*.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [Architecture](#2-architecture)
3. [Technology Stack](#3-technology-stack)
4. [Requirements](#4-requirements)
5. [Repository Structure](#5-repository-structure)
6. [Configuration Mastery](#6-configuration-mastery)
7. [The Runtime Layer (`src/app.tsx`)](#7-the-runtime-layer-srcapptsx)
8. [Request & Error Handling](#8-request--error-handling)
9. [Access Control & Permissions](#9-access-control--permissions)
10. [Internationalization Internals](#10-internationalization-internals)
11. [The API Contract & Code Generation](#11-the-api-contract--code-generation)
12. [The Demo Backend (Cloudflare Worker)](#12-the-demo-backend-cloudflare-worker)
13. [Mock System](#13-mock-system)
14. [Security Analysis](#14-security-analysis)
15. [Build & Tooling](#15-build--tooling)
16. [Deployment](#16-deployment)
17. [Testing Strategy](#17-testing-strategy)
18. [Operations & Maintenance](#18-operations--maintenance)
19. [Code Quality & Conventions](#19-code-quality--conventions)
20. [Potential Improvements](#20-potential-improvements)
21. [Quick Reference](#21-quick-reference)

---

## 1. Executive Summary

**Ant Design Pro** is an out-of-the-box UI solution for enterprise applications, distributed as a React boilerplate rather than an installable library. It is maintained by the Ant Design team as the canonical "starter" for building admin consoles, internal tools, and data dashboards on the Ant Design ecosystem.

**What it provides on day one:**

- A configurable application shell (ProLayout) with sidebar/top/mixed navigation, theme switching, and a settings drawer.
- Authentication and route-level access control, pre-wired.
- A dozen production-shaped page templates (dashboards, forms, CRUD tables, lists, profiles, results, exceptions, account pages) and a new AI chat page.
- Internationalization across eight locales.
- A mock-data system and a standalone demo backend, so the UI runs with zero backend setup.
- An OpenAPI-driven code generator for the API service layer.
- A modern toolchain: Vitest, Biome, and the utoopack (Turbopack-based) bundler.

**What it is *not*:** a backend, an authentication system, or a finished product. The bundled login and permissions are demonstrations. Adopting Pro means inheriting a well-structured frontend foundation and then supplying your own API, auth, and business logic.

**Version under analysis:** `6.0.2` (v6 line) — a substantial modernization featuring React 19, antd 6, UmiJS Max 4, Tailwind CSS v4, React Query, Biome, and the Ant Design X AI components.

> [!NOTE]
> The single most important architectural fact: **almost all behavior is framework configuration, not bespoke code.** The menu, routing, login redirect, request handling, permission checks, and i18n are UmiJS Max plugin features driven by `config/config.ts`. Understanding Max is understanding Pro.

---

## 2. Architecture

Ant Design Pro is a **single-page application** compiled to static assets. There is no application server in the product itself — the "backend" in this repository is a demo only.

### High-level component diagram

```text
┌──────────────────────────────────────────────────────────────────┐
│                         Browser (SPA)                              │
│                                                                    │
│   ┌──────────────────────────────────────────────────────────┐   │
│   │  UmiJS Max runtime                                         │   │
│   │   ├─ Router (config/routes.ts → code-split pages)          │   │
│   │   ├─ Layout plugin → ProLayout shell (sidebar/header)      │   │
│   │   ├─ Access plugin → src/access.ts (canAdmin, ...)         │   │
│   │   ├─ Initial State → src/app.tsx getInitialState()         │   │
│   │   ├─ Request plugin (axios) → src/requestErrorConfig.ts    │   │
│   │   ├─ React Query → server-state cache                      │   │
│   │   ├─ Locale plugin → src/locales/* (8 languages)           │   │
│   │   └─ Model plugin → src/models/* (useModel global state)   │   │
│   └──────────────────────────────────────────────────────────┘   │
│                                                                    │
│   Pages (src/pages/*)  ←uses→  Services (src/services/*)           │
│        │                              │                            │
└────────┼──────────────────────────────┼───────────────────────────┘
         │ /api/* (HTTP)                 │
         ▼                               ▼
  ┌─────────────────┐          ┌──────────────────────────────┐
  │  Dev: mock/*    │   OR     │  Dev proxy → your backend     │
  │  & **/_mock.ts  │          │  (config/proxy.ts)            │
  └─────────────────┘          └──────────────────────────────┘
                                          │
                                          ▼
                          ┌──────────────────────────────────┐
                          │  Demo backend (cloudflare-worker/)│
                          │  Hono app, ~33 routes, fake data  │
                          │  pro-api.ant-design-demo.workers  │
                          └──────────────────────────────────┘
```

### Request lifecycle

1. A page component calls a typed function in `src/services/ant-design-pro/` (e.g. `rule(params)`).
2. That function calls UmiJS Max's `request` (axios under the hood), which applies the config in `src/app.tsx` (`baseURL`) and the interceptors/error handlers in `src/requestErrorConfig.ts`.
3. In development with mocks, the request is answered locally; without mocks it goes through the `config/proxy.ts` proxy to a real backend.
4. Responses follow a `{ success, data, errorCode?, errorMessage?, showType? }` envelope; the error handler maps `showType` to a UI affordance (silent / warning / error message / notification / redirect).
5. For cached server state, pages wrap calls in React Query (`useQuery` / `useMutation`).

### Startup & auth gate

On boot, `getInitialState()` (in `src/app.tsx`) fetches the current user unless the route is a public auth page (`/user/login`, `/user/register`, `/user/register-result`). The result populates global state. The layout's `onPageChange` and the route `access` rules then gate navigation: an unauthenticated user is redirected to `/user/login?redirect=<original-path>`.

> [!IMPORTANT]
> The architecture cleanly separates **framework concerns** (routing, layout, request, access, i18n — all in `config/` and `src/app.tsx`) from **business concerns** (pages and services). When you adopt Pro, you mostly touch the latter. This separation is what makes the bundled `/pro-upgrade` skill able to merge framework updates without clobbering your code.

---

## 3. Technology Stack

| Layer | Technology | Version (declared) | Role |
|---|---|---|---|
| **UI library** | React | `^19.2.5` | Component runtime. |
| **Framework** | UmiJS Max (`@umijs/max`) | `^4.6.64` | Routing, data flow, request, access, layout, i18n. |
| **Component kit** | antd | `^6.4.3` | Core Ant Design components. |
| **Pro components** | `@ant-design/pro-components` | `^3.1.12` | High-level templates: ProLayout, ProTable, ProForm, etc. |
| **Charts** | `@ant-design/plots` | `^2.6.8` | Dashboard visualizations. |
| **Maps** | `d3` + `topojson-client` | `^7.9.0` / `^3.1.0` | Monitor-page geographic map. |
| **AI components** | `@ant-design/x`, `x-sdk`, `x-markdown` | `^2.8.0` | The AI Assistant chat page. |
| **Server state** | `@tanstack/react-query` | `^5.101.0` | Caching, mutations, invalidation. |
| **Styling** | Tailwind CSS v4 + antd-style + CSS Modules | `^4.3.0` / `^4.1.0` | Layered styling strategy. |
| **Dates** | dayjs | `^1.11.20` | Replaces moment (via the `moment2dayjs` plugin). |
| **Bundler** | utoopack (`@utoo/pack`) | via `@umijs/max` | Turbopack-based, Webpack-compatible build. |
| **Lint/format** | Biome | `^2.5.0` | Single tool replacing ESLint + Prettier. |
| **Tests** | Vitest | `4.1.8` | Unit/component tests (happy-dom). |
| **API codegen** | `@umijs/max-plugin-openapi` | `^2.0.3` | Generates services from OpenAPI. |
| **Demo backend** | Hono | `^4.6.0` | Cloudflare Worker mock API. |

> [!NOTE]
> The v6 upgrade was a deliberate "state of the art" refresh: class → functional components, moment → dayjs, Less → Tailwind/antd-style, useRequest → React Query, ESLint/Prettier → Biome, and Webpack → utoopack. If you're migrating from a v5 Pro project, budget for all of these shifts.

---

## 4. Requirements

| Requirement | Value | Source |
|---|---|---|
| Node.js | `>= 22.0.0` | `package.json` `engines.node` |
| Package manager | npm / pnpm / yarn | — |
| Build output | Static files (`dist/`) | `max build` |
| Hosting | Any static host or CDN | SPA; needs SPA fallback routing |
| Browsers | Modern (`browserslist: ["defaults"]`) | No IE support |

> [!WARNING]
> Because the app is a client-routed SPA, your static host **must** fall back unknown paths to `index.html` (so deep links like `/dashboard/analysis` work on refresh). On Nginx use `try_files $uri /index.html;`; on object stores enable single-page-application fallback. Without it, refreshing a sub-route returns a 404 from the host.

---

## 5. Repository Structure

```text
ant-design-pro/
├── config/                  # UmiJS Max build & framework configuration
│   ├── config.ts            #   Main config — enables every Max plugin
│   ├── routes.ts            #   Route table (the feature/menu map)
│   ├── routes.simple.ts     #   Minimal route table (used by `npm run simple`)
│   ├── defaultSettings.ts   #   ProLayout look & feel
│   ├── proxy.ts             #   Dev-server proxy targets (per UMI_ENV)
│   ├── oneapi.json          #   OpenAPI 3.0 contract → drives codegen
│   └── md-raw-loader.cjs    #   Loader to import .md as raw strings
├── mock/                    # Global mock endpoints (auto-registered)
├── cloudflare-worker/       # Standalone demo backend (Hono)
│   ├── src/index.ts         #   App entry, CORS, route mounting
│   ├── src/routes/*.ts      #   Route groups (user, table, dashboard, ...)
│   ├── src/data/*.ts        #   Fake data generators
│   └── wrangler.toml        #   Cloudflare deploy config
├── src/
│   ├── app.tsx              # Runtime config: getInitialState, layout, request, rootContainer
│   ├── access.ts            # Permission flags (canAdmin, ...)
│   ├── requestErrorConfig.ts# Request/response interceptors + error mapping
│   ├── global.tsx / .less / .style.ts  # Global styles & Tailwind entry
│   ├── service-worker.js    # PWA service worker (Workbox)
│   ├── manifest.json        # PWA manifest
│   ├── components/          # Shared components (layout + business)
│   ├── locales/             # i18n — 8 locales × 7 files each
│   ├── pages/               # Page templates (the demos)
│   ├── services/            # API client layer (generated + handwritten)
│   └── utils/               # Utilities (e.g. format.ts)
├── docs/                    # Project docs (cheatsheet.en-US.md / zh-CN.md, roadmap)
├── tests/                   # Test setup & mocks
├── types/                   # Ambient type declarations
├── biome.json               # Biome lint/format config
├── tailwind.config.js       # Tailwind content globs
├── vitest.config.ts         # Vitest config (happy-dom, aliases)
└── package.json
```

> [!TIP]
> Two directories carry almost all the framework wiring: **`config/`** (build-time) and the three runtime files **`src/app.tsx`**, **`src/access.ts`**, **`src/requestErrorConfig.ts`**. Read those five files and you understand the whole application skeleton.

---

## 6. Configuration Mastery

### `config/config.ts` — the plugin enable-map

This file is the heart of the build. It calls `defineConfig({...})` and turns on every UmiJS Max feature the template uses. Each key is a plugin or a core option.

| Key | Purpose | Notes |
|---|---|---|
| `hash: true` | Filename hashing for cache-busting | Recommended for production deploys. |
| `publicPath: '/'` | Base path for assets | Change for sub-path deploys. |
| `routes` | The route table | Imported from `config/routes.ts`. |
| `ignoreMomentLocale: true` | Drop moment locale data | Smaller bundle (moment is replaced by dayjs anyway). |
| `proxy` | Dev proxy | Selected by `UMI_ENV` from `config/proxy.ts`. |
| `fastRefresh: true` | React Fast Refresh | State-preserving HMR. |
| `routePrefetch: {}` | Prefetch route chunks | Faster navigation. |
| `manifest: {}` | Emit an asset manifest | Pairs with prefetch. |
| `model: {}` | Data-flow plugin | Enables `src/models/*` + `useModel`. |
| `initialState: {}` | Global initial state | Powers `getInitialState` in `app.tsx`. |
| `title: 'Ant Design Pro'` | App title | Header + document title. |
| `layout: { locale: true, ...defaultSettings }` | ProLayout | Merges `defaultSettings.ts`. |
| `moment2dayjs` | Replace moment with dayjs | Preset `antd`, plus duration/relativeTime plugins. |
| `locale` | i18n | `default: 'zh-CN'`, `antd: true`, `baseNavigator: true`. |
| `antd` | antd integration | `configProvider` sets variant `filled` and a custom font token. |
| `request: {}` | Unified request | axios + `useRequest`; configured in `app.tsx`. |
| `reactQuery: {}` | React Query plugin | Provides the QueryClient. |
| `access: {}` | Permission plugin | Reads `src/access.ts`; requires `initialState`. |
| `analytics: { ga_v2: 'G-...' }` | Google Analytics 4 | Replace or remove the GA tag for your own site. |
| `headScripts` | Extra `<head>` scripts | Ships a `loading.js` to avoid first-paint blank screen. |
| `plugins` | Extra plugins | `@umijs/max-plugin-openapi`, `@umijs/request-record`. |
| `openAPI` | OpenAPI codegen config | Reads `config/oneapi.json`; `mock: false`. |
| `tailwindcss: {}` | Tailwind v4 plugin | — |
| `mock` | Mock matching globs | Includes `src/pages/**/_mock.ts`. |
| `utoopack` | Bundler options | Custom `*.md` raw loader rule. |
| `requestRecord: {}` | Request recording | Used by `npm run record`. |
| `exportStatic: {}` | Static HTML export | Pre-renders routes for static hosting. |
| `define` | Build-time constants | Injects `COMMIT_HASH`, app/umi/utoo versions, `CI`. |

> [!CAUTION]
> The config hard-codes a **Google Analytics measurement ID** (`analytics.ga_v2`). Remove it or replace it with your own before deploying, or your traffic will report into the template's analytics property.

### `config/defaultSettings.ts` — ProLayout appearance

The layout look & feel. See the [User Guide](/guides/ant-design/ant-design-pro/user-guide/) for the per-field table. Key defaults: `navTheme: 'light'`, `colorPrimary: '#1677ff'`, `layout: 'mix'`, `contentWidth: 'Fluid'`, `fixSiderbar: true`.

### `config/proxy.ts` — environment proxies

Exports proxy maps keyed by `UMI_ENV` (`dev`, `test`, `pre`). Each maps `/api/` to a target with `changeOrigin: true`. The `test` environment points at the public demo Worker; `dev` is commented out (you fill it in); `pre` is a placeholder.

```ts
test: {
  '/api/': {
    target: 'https://pro-api.ant-design-demo.workers.dev',
    changeOrigin: true,
  },
},
```

> [!WARNING]
> Proxies apply **only to the dev server**. They are absent from production builds. This is the single most common source of "works locally, 404s in prod" confusion. In production, route `/api/*` at your infrastructure layer or set an absolute `request.baseURL`.

### Environment variables

A frontend scaffold has very few runtime env vars. The ones present:

| Variable | Where | Purpose |
|---|---|---|
| `UMI_ENV` | start scripts | Selects the proxy/config profile (`dev`/`test`/`pre`). |
| `MOCK` | start scripts | `MOCK=none` disables mock data. |
| `NODE_ENV` | `src/app.tsx` | `development` toggles dev-only behavior (dev API base URL, OpenAPI link). |
| `CHAT_API_URL` | `src/pages/chatbot/service.ts` | Override the AI chat model endpoint. |
| `COMMIT_HASH` / `CF_PAGES_COMMIT_SHA` | `config/config.ts` | Commit stamp; falls back to `git rev-parse HEAD` at build time. |
| `CI` | `config/config.ts` | Build-environment flag. |
| `ANALYZE` | `analyze` script | Enables bundle analysis. |

---

## 7. The Runtime Layer (`src/app.tsx`)

`src/app.tsx` is UmiJS Max's **runtime configuration** file — it exports specially-named members that the framework wires in at runtime.

| Export | Type | Responsibility |
|---|---|---|
| `getInitialState()` | async function | Fetch global startup data (the current user) and seed `settings`. Skips the fetch on auth pages. On fetch failure, redirects to login with a `redirect` param. |
| `layout` | `RunTimeLayoutConfig` | Configures ProLayout: menu item rendering (with prefetch links), header actions (doc link, version dropdown, language dropdown), avatar dropdown, footer, the per-page auth check (`onPageChange`), background images, and the Setting Drawer. Replaces ProLayout's default ErrorBoundary with an offline-aware one. |
| `request` | `RequestConfig` | Sets `baseURL` (empty in dev so the proxy/mock handles it; the demo Worker URL in production) and spreads in `errorConfig`. |
| `rootContainer` | function | Wraps the whole app in `<OfflineBanner>` and `<ErrorBoundary>`. |

> [!NOTE]
> `getInitialState` runs once at startup. The user object it returns flows into `src/access.ts` (to compute permissions) and into the layout (to render the avatar and gate pages). This is the backbone of the auth experience — re-implement `fetchUserInfo` to call your real identity endpoint.

---

## 8. Request & Error Handling

`src/requestErrorConfig.ts` defines the unified request/response behavior. It centers on a response envelope and a `showType` enum that decides how errors surface to the user.

**Response envelope:**

```ts
interface ResponseStructure {
  success: boolean;
  data: unknown;
  errorCode?: number;
  errorMessage?: string;
  showType?: ErrorShowType;
}
```

**`ErrorShowType` → UI behavior:**

| `showType` | Value | Behavior |
|---|---|---|
| `SILENT` | 0 | Do nothing. |
| `WARN_MESSAGE` | 1 | `message.warning(...)` toast. |
| `ERROR_MESSAGE` | 2 | `message.error(...)` toast. |
| `NOTIFICATION` | 3 | `notification.open(...)` panel. |
| `REDIRECT` | 9 | Redirect to `/user/login`. |

The config has three parts:

- **`errorThrower`** — when `success` is `false`, throws a custom `BizError` carrying `{ errorCode, errorMessage, showType, data }`.
- **`errorHandler`** — catches errors: honors `opts.skipErrorHandler`; maps `BizError` by `showType`; handles raw axios errors (`Response status:<code>`), offline state (a localized "network unavailable" message), and missing-response cases.
- **`requestInterceptors`** — a single pass-through interceptor with a **commented-out token-attachment example**. This is where you add `Authorization: Bearer <token>`.

> [!IMPORTANT]
> The token-attachment interceptor ships **disabled** (commented out). The demo never sends an auth header. To integrate real auth, uncomment and complete the interceptor to read your token (from memory, cookie, or storage) and attach it. The most-requested community feature — silent token refresh ([#11550](https://github.com/ant-design/ant-design-pro/issues/11550), [#11869](https://github.com/ant-design/ant-design-pro/issues/11869)) — is implemented here too, by adding a 401 response interceptor that refreshes and retries.

---

## 9. Access Control & Permissions

Permissions are computed in `src/access.ts`, a single function that receives the initial state and returns a flag map:

```ts
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) {
  const { currentUser } = initialState ?? {};
  return {
    canAdmin: currentUser && currentUser.access === 'admin',
  };
}
```

The flags are consumed three ways:

1. **Route-level:** add `access: 'canAdmin'` to a route in `config/routes.ts`. Unauthorized routes are hidden from the menu and blocked. (The demo `/admin` route uses this.)
2. **Component-level (declarative):** `<Access accessible={access.canAdmin}><AdminPanel/></Access>`.
3. **Component-level (imperative):** `const access = useAccess(); if (access.canAdmin) {...}`.

To add a permission, add a flag to the returned object (e.g. `canUser: !!currentUser`, `canEditOrders: currentUser?.roles?.includes('order-editor')`) and reference it in routes/components.

> [!NOTE]
> Access flags are **derived from the current user**, which comes from your identity endpoint. This is purely a client-side convenience for UX (hiding menus, gating views). It is **not** a security boundary — every protected operation must also be authorized server-side. A determined user can call your API directly regardless of what the menu shows.

---

## 10. Internationalization Internals

The i18n system is the UmiJS Max `locale` plugin. Each locale is a directory under `src/locales/<locale>/` plus an entry file `src/locales/<locale>.ts`. Strings are split by concern:

| File | Covers |
|---|---|
| `menu.ts` | Navigation menu labels (`menu.<route-name>`). |
| `pages.ts` | Page content strings. |
| `component.ts` | Shared component strings. |
| `globalHeader.ts` | Header/search/notifications. |
| `settings.ts` / `settingDrawer.ts` | Setting drawer labels. |
| `network.ts` | Network/error strings. |

Eight locales ship: `zh-CN` (default), `zh-TW`, `en-US`, `ja-JP`, `pt-BR`, `id-ID`, `fa-IR`, `bn-BD`. The language switcher (`src/components/RightContent/index.tsx`) maps each locale to a flag emoji and native label and only renders when more than one supported locale is present.

> [!TIP]
> To trim bundle size for a single-language deployment, set `locale.default` to your language, delete unused locale directories, and (optionally) run `npm run i18n-remove` to inline strings and remove the `FormattedMessage`/`useIntl` wrappers entirely.

---

## 11. The API Contract & Code Generation

The service layer in `src/services/ant-design-pro/` is **generated** from an OpenAPI document, not handwritten.

- **`config/oneapi.json`** is an OpenAPI 3.0 spec describing the frontend's expected API: `currentUser`, `login`, `outLogin`, `getFakeCaptcha`, `getNotices`, and `rule` CRUD (`GET`/`POST`/`PUT`/`DELETE /api/rule`), plus the shared schemas (`CurrentUser`, `LoginParams`, `LoginResult`, `RuleListItem`, `RuleList`, `NoticeIconItem`, `ErrorResponse`, ...).
- Running **`npm run openapi`** (the `@umijs/max-plugin-openapi` plugin) regenerates `src/services/ant-design-pro/api.ts`, `login.ts`, `index.ts`, and the `typings.d.ts` `declare namespace API {...}` types.

The generated functions are thin wrappers over `request`:

```ts
export async function rule(params: { current?: number; pageSize?: number }, options?) {
  return request<API.RuleList>('/api/rule', { method: 'GET', params, ...(options || {}) });
}
```

> [!IMPORTANT]
> Files under `src/services/ant-design-pro/` are **auto-generated — never edit them by hand.** To change the API surface, edit `config/oneapi.json` (or point `schemaPath` at your live OpenAPI endpoint) and run `npm run openapi`. Hand edits are silently overwritten on the next generation. The generated types (`API.*`) are the canonical request/response types used throughout the pages.

---

## 12. The Demo Backend (Cloudflare Worker)

To make the live preview and `test` environment work without a real backend, the repo includes a standalone API under `cloudflare-worker/` — a [Hono](https://hono.dev) app deployed as a Cloudflare Worker (`pro-api.ant-design-demo.workers.dev`). It is a separate package (`pro-api`, its own `package.json`) and is **not** part of your application build.

**Entry (`cloudflare-worker/src/index.ts`):** sets up CORS with an origin allowlist (`utils/cors.ts`), exposes `/api/auth_routes`, mounts ten route groups under `/api`, and returns a JSON 404 for unmatched paths.

**Route groups (~33 endpoints total):**

| Group | File | Representative endpoints |
|---|---|---|
| User/auth | `routes/user.ts` | `POST /api/login/account` (always returns admin), `POST /api/login/outLogin`, `GET /api/login/captcha`, `POST /api/register`, `GET /api/currentUser`, `GET /api/users` |
| Table | `routes/table.ts` | `GET /api/rule` (search/sort/filter/paginate), `POST /api/rule` (create/update/delete by `method` field) |
| Dashboard | `routes/dashboard.ts` | `GET /api/fake_analysis_chart_data`, `/fake_workplace_chart_data`, `/project/notice`, `/activities` |
| List | `routes/list.ts` | `GET /api/get_list`, `POST /api/post_fake_list`, `/fake_list`, `/card_fake_list`, `/tags`, ... |
| Monitor | `routes/monitor.ts` | `GET /api/monitor/tags`, `/map-geo`, `/map-grid` |
| Geographic | `routes/geographic.ts` | `GET /api/geographic/province`, `/city/:province` |
| Profile | `routes/profile.ts` | `GET /api/profile/basic`, `/advanced` |
| Settings | `routes/settings.ts` | `GET /api/accountSettingCurrentUser` |
| Notices | `routes/notices.ts` | `GET /api/notices` |
| Errors | `routes/errors.ts` | `GET /api/401`, `/403`, `/404`, `/500` (status-code demos) |

**Notable production-minded touches in the demo code:** the list endpoints clamp the `count` query to `[1, 100]` to prevent memory exhaustion; the table endpoint validates JSON bodies and `sorter`/`filter` shapes, returning `400` on malformed input; CORS falls back to a safe default origin for disallowed origins.

> [!CAUTION]
> The demo backend exists to make the UI runnable, not to be used as a real API. Its login **grants admin to anyone**, it stores no data persistently, and its responses are randomized/fake. Stand up your own backend and repoint `config/proxy.ts` (dev) and `request.baseURL` (prod) at it.

---

## 13. Mock System

Independent of the Worker, the project supports in-process mocking handled by UmiJS:

- **Global mocks:** `mock/*.ts` (e.g. `mock/user.ts`, `mock/listTableList.ts`, `mock/notices.ts`, `mock/route.ts`) — exported objects keyed by `'METHOD /path'`.
- **Page-level mocks:** `src/pages/**/_mock.ts`, matched by the `mock.include` glob in `config/config.ts`.

Mocks are active in `dev` mode unless `MOCK=none`. The data layer uses `mockjs` for realistic random data.

> [!TIP]
> Mocks (`mock/` + `_mock.ts`) and the Cloudflare Worker are two *separate* fake-backend mechanisms. Use **mocks** for local, offline UI work (the `npm start` default). The **Worker** backs the hosted preview and the `test` environment. You generally won't ship either — they're development scaffolding.

---

## 14. Security Analysis

Ant Design Pro is a frontend; its security surface is correspondingly narrow, but there are real items to address before production.

### What's already handled

| Control | Where | Detail |
|---|---|---|
| **Open-redirect protection** | `src/pages/user/login/index.tsx` | `getSafeRedirectUrl` rejects non-relative URLs, protocol-relative `//host` URLs, and cross-origin targets — only same-origin relative paths are honored after login. |
| **Service-worker origin check** | `src/service-worker.js` | The `message` listener verifies `event.origin === self.location.origin` before acting, preventing cross-origin postMessage abuse. |
| **Worker CORS allowlist** | `cloudflare-worker/src/utils/cors.ts` | The demo backend restricts allowed origins, with a safe default for disallowed ones. |
| **Input clamping/validation** | `cloudflare-worker/src/routes/*.ts` | List counts clamped to `[1,100]`; JSON/sorter/filter validated with `400` on bad input. |

### What you must add

> [!WARNING]
> The bundled authentication is a **demo, not a security control.** Before production:
> - **Implement real authentication.** The mock login grants admin to everyone and the request interceptor that would attach an auth token is commented out (`src/requestErrorConfig.ts`).
> - **Enforce authorization server-side.** `src/access.ts` flags only hide UI; they do not protect data. Every privileged API call must be authorized on the server.
> - **Choose secure token handling.** Decide between httpOnly cookies (XSS-resistant) and in-memory/storage tokens, and implement refresh. The template leaves this to you.
> - **Remove demo endpoints and IDs.** Drop the demo `request.baseURL` pointing at `workers.dev`, replace the hard-coded GA tag, and point the AI chat at your own gateway (not the public demo model).
> - **Set security headers and CSP** at your hosting/proxy layer (the SPA can't set its own response headers).

### Dependency posture

The app pulls in a broad set of dependencies (charts, D3, AI components, React Query). Run `npm audit` regularly and keep antd/UmiJS Max current — the `/pro-upgrade` skill helps track template-level updates.

---

## 15. Build & Tooling

### Bundler: utoopack

v6 builds with **utoopack** (`@utoo/pack`), a next-generation, Turbopack-based bundler that is Webpack-compatible. It's configured via the `utoopack` field in `config/config.ts` and supports `module.rules` for custom loaders (the template registers a raw loader for `*.md` so pages like Welcome can import Markdown as a string).

### Lint & format: Biome

`biome.json` configures a single tool for both linting and formatting (replacing ESLint + Prettier). Highlights: single quotes, space indentation, classic JSX runtime, and a curated rule set with several `a11y`/`correctness` rules relaxed for this template. Generated and vendored paths (`src/services`, `mock`, `dist`, `.umi*`, `node_modules`) are excluded.

```bash
npm run lint     # Biome lint + tsc --noEmit
npm run biome    # auto-fix (format + lint)
```

### Type checking

`npm run tsc` runs `tsc --noEmit` against a TypeScript `^6.0.3` toolchain. Type checking is part of `npm run lint`, so CI catches type regressions.

> [!NOTE]
> Coverage (`codecov.yml`) is **informational only** — it does not block PRs. Small fixes often ship without tests; dedicated test PRs raise coverage. Adopt your own gate if you need a hard coverage floor.

---

## 16. Deployment

The build is static, so deployment is "serve a folder," with two caveats: SPA fallback routing and `publicPath`.

### Standard flow

```bash
npm run build      # → dist/
# upload dist/ to your static host / CDN / bucket
```

### Sub-path deploys

Set `publicPath` in `config/config.ts` to the sub-path (e.g. `'/admin/'`) so hashed asset URLs resolve. The default is `'/'`.

### GitHub Pages

`npm run deploy` builds and pushes `dist/` to the `gh-pages` branch via the `gh-pages` package. A `public/CNAME` is present for custom-domain Pages hosting.

### PWA

The repo ships a Workbox service worker (`src/service-worker.js`) and a web app manifest (`src/manifest.json`, with icons). The service worker uses a network-first strategy for `/api/*` and selected CDN assets, and an origin-checked skip-waiting handshake.

> [!IMPORTANT]
> Configure SPA fallback on your host (route unknown paths to `index.html`) or client-side deep links will 404 on refresh. For Cloudflare Pages, enable single-page-application not-found handling; for Nginx, use `try_files $uri $uri/ /index.html;`.

### Production checklist

- [ ] Set `request.baseURL` (or same-origin `/api`) to your real backend in `src/app.tsx`.
- [ ] Implement real auth and uncomment/complete the token interceptor.
- [ ] Replace or remove the Google Analytics ID in `config/config.ts`.
- [ ] Repoint or remove the AI chat endpoint (`CHAT_API_URL`).
- [ ] Set `publicPath` if deploying under a sub-path.
- [ ] Configure SPA fallback routing on the host.
- [ ] Add security headers / CSP at the proxy/CDN.
- [ ] Run `npm run lint && npm run build` clean.

---

## 17. Testing Strategy

Tests use **Vitest** with the `happy-dom` environment and Testing Library.

| Aspect | Detail |
|---|---|
| Runner | Vitest `4.1.8` (`npm test` / `:coverage` / `:watch` / `:ui`). |
| Environment | `happy-dom`, globals enabled, `tests/setupTests.ts` as setup. |
| Match | `src/**/*.{test,spec}.{ts,tsx}`. |
| Coverage | v8 provider; excludes `.umi`, generated services, `*.d.ts`, `*.style.ts`. |
| Aliases | `@ → src`, `@@ → src/.umi`, `@root → repo root`. |

Representative existing tests: `src/access.test.ts` (permission logic), `src/app.test.tsx` (`getInitialState` redirect-on-401 behavior), `src/requestErrorConfig.test.ts` (every `showType` branch and axios/offline error paths), and `src/pages/table-list/index.test.tsx` (ProTable rendering and the `rule` API call).

> [!NOTE]
> One Umi-integration test (`src/pages/user/login/login.test.tsx`) is **excluded** from Vitest because it depends on Umi's own Jest infrastructure. A migration from Jest to Vitest is in progress ([#11823](https://github.com/ant-design/ant-design-pro/issues/11823)); if you adopt the template, standardize on Vitest for new tests.

---

## 18. Operations & Maintenance

Because there's no server runtime in the product, "operations" is mostly about CI, upgrades, and keeping the static deploy healthy.

| Task | How |
|---|---|
| **Local dev** | `npm start` (mock) or `npm run dev` (proxied backend). |
| **CI gate** | `npm run lint && npm test && npm run build`. |
| **Upgrade the template** | `npx skills add ant-design/ant-design-pro` then `/pro-upgrade` in Claude Code — diffs the latest template and merges framework changes while preserving business code. |
| **Regenerate API client** | Edit `config/oneapi.json`, run `npm run openapi`. |
| **Bundle analysis** | `npm run analyze`. |
| **Reset a broken dev server** | `rm -rf src/.umi && npm start`. |
| **Deploy the demo backend** | `cd cloudflare-worker && npm run deploy` (Wrangler) — only if you want your own demo API. |

### Built-in AI skills

The repo ships two Claude Code skills under `.claude/skills/`:

- **`/pro-upgrade`** — clones the latest template, classifies framework vs. business files, merges dependency/config/code-pattern updates, runs `npx antd lint`, and verifies with `npm run lint && npm run build`.
- **`/antd`** — queries antd component APIs, props, tokens, and demos; lints for deprecated usage; assists version migrations — via `@ant-design/cli` with offline metadata.

---

## 19. Code Quality & Conventions

| Convention | Rule |
|---|---|
| **Generated code** | `src/services/ant-design-pro/` is generated — never edit by hand; change `oneapi.json` and regenerate. |
| **Commits** | Conventional Commits enforced via commitlint + Husky (`feat:`, `fix:`, `chore:`, ...). |
| **Lint/format** | Biome only — do not add ESLint or Prettier. `npx antd lint ./src` should pass clean. |
| **Styling priority** | Tailwind (layout) → antd-style (theme tokens) → CSS Modules (component) → Less (legacy global only). |
| **Path aliases** | `@/*` → `src/*`; `@@/*` → `src/.umi/*` (Umi temp). |
| **Mock priority** | `mock/` for global, `src/pages/**/_mock.ts` for page-level; both auto-registered. |
| **Components** | Functional components throughout (class components removed in v6). |
| **Temp dir** | `src/.umi` is generated; never commit it. Delete + restart if behavior is odd. |

> [!NOTE]
> **Negative knowledge — things that do NOT exist here, so don't look for them:** there is no application server in the product (the Worker is a separate demo); no runtime database or ORM; no environment-variable-driven app config beyond the handful listed in §6; no real authentication, session store, or token persistence; no ESLint/Prettier (Biome replaces them); no Webpack config (utoopack); no Redux/MobX (state is `useModel` + React Query + `getInitialState`).

---

## 20. Potential Improvements

Drawn from the code, the project's own roadmap, and community issues — the work most teams do after adopting Pro.

### Authentication & session

- **Implement real auth and token refresh.** Complete the commented-out request interceptor; add a 401 response interceptor with silent refresh and a concurrent-request queue. This is the single most-requested capability ([#11550](https://github.com/ant-design/ant-design-pro/issues/11550), [#11869](https://github.com/ant-design/ant-design-pro/issues/11869)).
- **Dynamic routes/menus from the backend.** Several teams want server-driven menus after login ([#11802](https://github.com/ant-design/ant-design-pro/issues/11802)); UmiJS supports patching routes at runtime — wire it into `getInitialState`.

### UX & features

- **Multi-tab navigation** (keep-alive tabs) is a common enterprise request ([#11627](https://github.com/ant-design/ant-design-pro/issues/11627)).
- **Global search** in the header ([#11755](https://github.com/ant-design/ant-design-pro/issues/11755)).
- **Fix the sidebar/pagination overlay bug** ([#11597](https://github.com/ant-design/ant-design-pro/issues/11597), [#11821](https://github.com/ant-design/ant-design-pro/issues/11821)) — tracked for v6.1.0.

### Engineering hygiene

- **Finish the Jest → Vitest migration** ([#11823](https://github.com/ant-design/ant-design-pro/issues/11823)) and bring the excluded login test into the Vitest suite.
- **Tighten OpenAPI codegen** — naming/casing consistency fixes are tracked ([#11819](https://github.com/ant-design/ant-design-pro/issues/11819), [#11846](https://github.com/ant-design/ant-design-pro/issues/11846)).
- **Harden Windows install** — the `tailwindcss` resolution issue ([#11747](https://github.com/ant-design/ant-design-pro/issues/11747), [#11818](https://github.com/ant-design/ant-design-pro/issues/11818)) is fixed but worth verifying in your CI.
- **Raise the coverage floor** — coverage is informational; add a hard gate for your business code.

> [!TIP]
> Track the **v6.1.0 release** ([#11813](https://github.com/ant-design/ant-design-pro/issues/11813)) and use the `/pro-upgrade` skill to pull fixes. Because Pro cleanly separates framework files from business files, staying current is far cheaper here than in a hand-rolled scaffold.

---

## 21. Quick Reference

### Key files

| File | What it controls |
|---|---|
| `config/config.ts` | Build + all framework plugins. |
| `config/routes.ts` | Routes & menu (the feature map). |
| `config/defaultSettings.ts` | Layout/theme defaults. |
| `config/proxy.ts` | Dev proxy targets. |
| `config/oneapi.json` | API contract → codegen. |
| `src/app.tsx` | Runtime: initial state, layout, request, root container. |
| `src/access.ts` | Permission flags. |
| `src/requestErrorConfig.ts` | Request/response interceptors + error mapping. |

### Essential commands

| Command | Purpose |
|---|---|
| `npm start` | Dev server with mocks. |
| `npm run dev` / `start:no-mock` | Dev server, real backend via proxy. |
| `npm run build` | Production build → `dist/`. |
| `npm run preview` | Serve the build locally. |
| `npm run deploy` | Build + publish to GitHub Pages. |
| `npm run lint` | Biome + `tsc`. |
| `npm test` | Vitest. |
| `npm run openapi` | Regenerate API services. |
| `npm run simple` | Strip to minimal template (irreversible). |

### Default ports & URLs

| Item | Value |
|---|---|
| Dev / preview server | `http://localhost:8000` |
| Demo backend | `https://pro-api.ant-design-demo.workers.dev` |
| Live preview | `https://preview.pro.ant.design` |
| Demo login | `admin` / `ant.design` (or `user`), mobile captcha `1234` |

### Permission flags

| Flag | Definition |
|---|---|
| `canAdmin` | `currentUser.access === 'admin'` |

---

_Generated June 2026 from ant-design/ant-design-pro at 7f89ecb. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
