Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Ant Design Pro — Admin & Architecture Guide

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.

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 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
  2. Architecture
  3. Technology Stack
  4. Requirements
  5. Repository Structure
  6. Configuration Mastery
  7. The Runtime Layer (src/app.tsx)
  8. Request & Error Handling
  9. Access Control & Permissions
  10. Internationalization Internals
  11. The API Contract & Code Generation
  12. The Demo Backend (Cloudflare Worker)
  13. Mock System
  14. Security Analysis
  15. Build & Tooling
  16. Deployment
  17. Testing Strategy
  18. Operations & Maintenance
  19. Code Quality & Conventions
  20. Potential Improvements
  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

┌──────────────────────────────────────────────────────────────────┐
│                         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

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 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.

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:

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, #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:

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:

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 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.

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

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); 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, #11869).
  • Dynamic routes/menus from the backend. Several teams want server-driven menus after login (#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).
  • Global search in the header (#11755).
  • Fix the sidebar/pagination overlay bug (#11597, #11821) — tracked for v6.1.0.

Engineering hygiene

  • Finish the Jest → Vitest migration (#11823) and bring the excluded login test into the Vitest suite.
  • Tighten OpenAPI codegen — naming/casing consistency fixes are tracked (#11819, #11846).
  • Harden Windows install — the tailwindcss resolution issue (#11747, #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) 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'