docs: add localized docs routes and language content

Migrate docs to language-prefixed app routes and split content into zh/en trees, including translated English navigation and pages.

Made-with: Cursor
This commit is contained in:
zuiidea
2026-04-28 17:31:50 +08:00
parent f12539812e
commit 0726321552
81 changed files with 699 additions and 107 deletions
+21 -17
View File
@@ -4,31 +4,35 @@
## 内容目录(侧栏分组)
| 分组 | 路径(`content/` 下) |
|------|------------------------|
| 概述 | `index.mdx` |
| 欢迎 | `welcome/documentation-intro.mdx` |
| 入门 | `getting-started/`(快速开始、`folder-structure`、`available-scripts` …) |
| 模板 | `templates/`(模板列表、`basic`、`with-lingui`) |
| 开发 | `development/` |
| 样式与资源 | `styles-and-assets/` |
| 构建应用 | `building/` |
| 测试 | `testing/` |
| 后端对接 | `backend/` |
| 部署 | `deployment/` |
| 分组 | 路径(`content/` 下) |
| ----- | ----------------------------------------------------------------- |
| 概述 | `index.mdx` |
| 欢迎 | `welcome/documentation-intro.mdx` |
| 入门 | `getting-started/`(快速开始、`folder-structure`、`available-scripts` …) |
| 模板 | `templates/`(模板列表、`basic`、`with-lingui`) |
| 开发 | `development/` |
| 样式与资源 | `styles-and-assets/` |
| 构建应用 | `building/` |
| 测试 | `testing/` |
| 后端对接 | `backend/` |
| 部署 | `deployment/` |
侧边栏顺序与标题由各目录旁 `_meta.js` 及根目录 `content/_meta.js` 配置。
## 端口说明
| 项目 | 默认开发地址 |
| ---- | ------------ |
| 模板应用(`vp dev`) | [http://localhost:5173](http://localhost:5173) |
| 项目 | 默认开发地址 |
| ---------------- | ---------------------------------------------- |
| 模板应用(`vp dev`) | [http://localhost:5173](http://localhost:5173) |
| 本文档站(`pnpm dev`) | [http://localhost:3000](http://localhost:3000) |
## 常用命令
在 **`apps/docs`** 目录下:
在 `**apps/docs**` 目录下:
```bash
pnpm install # 首次或依赖变更后
@@ -46,4 +50,4 @@ cd apps/docs && pnpm install && pnpm dev
## 设计说明
初始实现见 `docs/specs/2026-04-15-apps-docs-nextra-plan.md`。
初始实现见 `docs/specs/2026-04-15-apps-docs-nextra-plan.md`。
-31
View File
@@ -1,31 +0,0 @@
import { generateStaticParamsFor, importPage } from "nextra/pages";
import { useMDXComponents as getMDXComponents } from "../../mdx-components";
export const generateStaticParams = generateStaticParamsFor("mdxPath");
/** Nextra Docs Theme 在运行时会提供 `wrapper`;类型上可能为 optional。 */
const Wrapper = getMDXComponents().wrapper!;
type PageProps = { params: Promise<{ mdxPath?: string[] }> };
export async function generateMetadata(props: PageProps) {
const params = await props.params;
const { metadata } = await importPage(params.mdxPath);
return metadata;
}
export default async function Page(props: PageProps) {
const params = await props.params;
const {
default: MDXContent,
toc,
metadata,
sourceCode,
} = await importPage(params.mdxPath);
return (
<Wrapper toc={toc} metadata={metadata} sourceCode={sourceCode}>
<MDXContent {...props} params={params} />
</Wrapper>
);
}
@@ -0,0 +1,33 @@
import { importPage } from "nextra/pages";
import type { ReactNode } from "react";
import { useMDXComponents as getMDXComponents } from "../../../mdx-components";
const Wrapper =
getMDXComponents().wrapper ?? ((props: { children?: ReactNode }) => <>{props.children}</>);
type PageProps = { params: Promise<{ lang: string; mdxPath?: string[] }> };
function normalizePath(pathSegments?: string[]) {
return (pathSegments ?? []).filter((segment): segment is string => Boolean(segment));
}
export async function generateMetadata(props: PageProps) {
const params = await props.params;
const mdxPath = normalizePath(params.mdxPath);
const { metadata } = await importPage(mdxPath, params.lang);
return metadata;
}
export default async function Page(props: PageProps) {
const params = await props.params;
const mdxPath = normalizePath(params.mdxPath);
const pageData = await importPage(mdxPath, params.lang);
const MDXContent = pageData.default ?? (() => null);
const { toc, metadata, sourceCode } = pageData;
return (
<Wrapper toc={toc} metadata={metadata} sourceCode={sourceCode}>
<MDXContent {...props} params={params} />
</Wrapper>
);
}
+98
View File
@@ -0,0 +1,98 @@
import { Footer, Layout, Navbar, NotFoundPage } from "nextra-theme-docs";
import { getPageMap } from "nextra/page-map";
import "nextra-theme-docs/style.css";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import type { ReactElement, ReactNode } from "react";
const LOCALES = ["zh", "en"] as const;
type Locale = (typeof LOCALES)[number];
function isLocale(value: string): value is Locale {
return (LOCALES as readonly string[]).includes(value);
}
function copyFor(locale: Locale) {
if (locale === "en") {
return {
htmlLang: "en",
title: "Antd Admin Docs",
description:
"Antd Admin template guide: choose between basic and with-lingui, then configure and run.",
};
}
return {
htmlLang: "zh-CN",
title: "Antd Admin 文档",
description: "antd-admin 模板使用说明:basic 与 with-lingui 选型、安装与配置。",
};
}
export async function generateMetadata({
params,
}: {
params: Promise<{ lang: string }>;
}): Promise<Metadata> {
const { lang } = await params;
if (!isLocale(lang)) return {};
const copy = copyFor(lang);
return {
title: {
default: copy.title,
template: `%s – ${copy.title}`,
},
description: copy.description,
};
}
export default async function RootLayout({
children,
params,
}: {
children: ReactNode;
params: Promise<{ lang: string }>;
}): Promise<ReactElement> {
const { lang } = await params;
if (!isLocale(lang)) notFound();
const copy = copyFor(lang);
const localizedPageMap = await getPageMap(`/${lang}`);
const pageMap = (Array.isArray(localizedPageMap) ? localizedPageMap : []).filter(Boolean);
return (
<html lang={copy.htmlLang} dir="ltr" suppressHydrationWarning>
<body>
<Layout
navbar={
<Navbar
logo={<b>{copy.title}</b>}
projectLink="https://github.com/zuiidea/antd-admin"
/>
}
pageMap={pageMap}
docsRepositoryBase="https://github.com/zuiidea/antd-admin/tree/master"
i18n={[
{ locale: "zh", name: "中文" },
{ locale: "en", name: "English" },
]}
footer={
<Footer>
MIT {new Date().getFullYear()} ©{" "}
<a href="https://github.com/zuiidea/antd-admin" rel="noreferrer" target="_blank">
antd-admin
</a>
</Footer>
}
>
{children}
</Layout>
</body>
</html>
);
}
export function NotFound() {
return <NotFoundPage />;
}
+5
View File
@@ -0,0 +1,5 @@
import { NotFoundPage } from "nextra-theme-docs";
export default function NotFound() {
return <NotFoundPage />;
}
-54
View File
@@ -1,54 +0,0 @@
import { Footer, Layout, Navbar } from "nextra-theme-docs";
import { Head } from "nextra/components";
import { getPageMap } from "nextra/page-map";
import "nextra-theme-docs/style.css";
import type { Metadata } from "next";
import type { ReactElement, ReactNode } from "react";
export const metadata: Metadata = {
title: {
default: "Antd Admin 文档",
template: "%s – Antd Admin 文档",
},
description: "antd-admin 模板使用说明:basic 与 with-lingui 选型、安装与配置。",
};
const navbar = (
<Navbar
logo={<b>Antd Admin 文档</b>}
projectLink="https://github.com/zuiidea/antd-admin"
/>
);
const footer = (
<Footer>
MIT {new Date().getFullYear()} ©{" "}
<a href="https://github.com/zuiidea/antd-admin" rel="noreferrer" target="_blank">
antd-admin
</a>
</Footer>
);
export default async function RootLayout({
children,
}: {
children: ReactNode;
}): Promise<ReactElement> {
const pageMap = await getPageMap();
return (
<html lang="zh-CN" dir="ltr" suppressHydrationWarning>
<Head />
<body>
<Layout
navbar={navbar}
pageMap={pageMap}
docsRepositoryBase="https://github.com/zuiidea/antd-admin/tree/master"
footer={footer}
>
{children}
</Layout>
</body>
</html>
);
}
+13
View File
@@ -0,0 +1,13 @@
/** @type {import('nextra').MetaRecord} */
export default {
index: "Overview",
welcome: "Welcome",
"getting-started": "Getting Started",
templates: "Templates",
development: "Development",
"styles-and-assets": "Styles & Assets",
building: "Building",
testing: "Testing",
backend: "Backend Integration",
deployment: "Deployment",
};
+4
View File
@@ -0,0 +1,4 @@
/** @type {import('nextra').MetaRecord} */
export default {
"proxying-api-requests": "Proxying API Requests",
};
@@ -0,0 +1,14 @@
---
title: Proxying API Requests
description: Configure API proxying between frontend and backend
---
# Proxying API Requests
Use a proxy layer in development to avoid CORS issues and keep API endpoints configurable.
Recommended approach:
- Define a consistent API prefix.
- Route requests by environment.
- Keep backend base URLs in environment variables.
+7
View File
@@ -0,0 +1,7 @@
/** @type {import('nextra').MetaRecord} */
export default {
"environment-variables": "Environment Variables",
performance: "Performance",
"production-build": "Production Build",
router: "Router",
};
@@ -0,0 +1,12 @@
---
title: Environment Variables
description: Manage environment configuration safely across environments
---
# Environment Variables
Use environment variables to separate configuration from code.
- Keep secrets out of source files.
- Use environment-specific values for dev/staging/prod.
- Document required variables for contributors.
@@ -0,0 +1,13 @@
---
title: Performance
description: Practical optimization checklist for admin applications
---
# Performance
Focus on practical wins:
- Reduce unnecessary rerenders
- Split heavy modules
- Cache requests where appropriate
- Measure before and after each optimization
@@ -0,0 +1,19 @@
---
title: Production Build
description: Build and validate for production deployment
---
# Production Build
Before deployment:
1. Run production build.
2. Verify lint and tests.
3. Validate key user flows in preview/staging.
Example:
```bash
pnpm --filter ./apps/basic build
pnpm --filter ./apps/with-lingui build
```
+14
View File
@@ -0,0 +1,14 @@
---
title: Router
description: Routing conventions and recommendations
---
# Router
Use clear route grouping and layout boundaries.
Recommendations:
- Keep feature routes close to feature modules
- Avoid deeply coupled route dependencies
- Handle auth/permission checks in a predictable layer
+15
View File
@@ -0,0 +1,15 @@
---
title: Deployment
description: Deployment guidance and rollout checklist
---
# Deployment
Before production rollout:
- Validate environment variables
- Run full build and tests
- Verify critical user journeys
- Set up monitoring and error tracking
Deploy progressively when possible and prepare a rollback plan.
@@ -0,0 +1,5 @@
/** @type {import('nextra').MetaRecord} */
export default {
"bundle-analysis": "Bundle Analysis",
"https-in-development": "HTTPS in Development",
};
@@ -0,0 +1,16 @@
---
title: Bundle Analysis
description: Analyze bundle size and optimize package usage
---
# Bundle Analysis
Use your build tooling and analyzer plugins to inspect bundle composition.
Focus on:
- Heavy dependencies
- Duplicate packages
- Over-imported UI modules
After optimization, rerun build and compare the output artifacts.
@@ -0,0 +1,10 @@
---
title: HTTPS in Development
description: Enable HTTPS for local development when needed
---
# HTTPS in Development
If your scenario requires secure context (for example some browser APIs), enable HTTPS in local dev by configuring your dev server certificates.
Keep certificates out of version control and share setup instructions with your team.
@@ -0,0 +1,9 @@
/** @type {import('nextra').MetaRecord} */
export default {
index: "Getting Started",
"available-scripts": "Available Scripts",
"folder-structure": "Folder Structure",
"supported-browsers": "Supported Browsers",
"supported-features": "Supported Features",
"updating-releases": "Updating Releases",
};
@@ -0,0 +1,44 @@
---
title: Available Scripts
description: Common pnpm scripts and usage in this monorepo
---
# Available Scripts
## Workspace-Level
```bash
pnpm install
pnpm -r build
pnpm -r lint
pnpm -r test
```
## docs (`apps/docs`)
```bash
pnpm --filter ./apps/docs dev
pnpm --filter ./apps/docs build
pnpm --filter ./apps/docs start
```
## basic (`apps/basic`)
```bash
pnpm --filter ./apps/basic dev
pnpm --filter ./apps/basic build
pnpm --filter ./apps/basic preview
```
## with-lingui (`apps/with-lingui`)
```bash
pnpm --filter ./apps/with-lingui dev
pnpm --filter ./apps/with-lingui build
pnpm --filter ./apps/with-lingui preview
```
## Notes
- Use `--filter` to scope commands to a single app.
- Run commands at the repository root for consistent workspace behavior.
@@ -0,0 +1,28 @@
---
title: Folder Structure
description: Key directories and responsibilities in the repository
---
# Folder Structure
```text
.
├─ apps/
│ ├─ basic/
│ ├─ with-lingui/
│ └─ docs/
├─ packages/
├─ pnpm-workspace.yaml
└─ turbo.json
```
## Directory Guide
- `apps/basic`: Main admin template (English)
- `apps/with-lingui`: Admin template with Lingui i18n
- `apps/docs`: Documentation site (Nextra + Next.js)
- `packages`: Shared packages and utilities
## Recommendation
When creating reusable logic, prioritize placing it in `packages` rather than duplicating in app folders.
@@ -0,0 +1,43 @@
---
title: Getting Started
description: Install dependencies, start development, and build applications
---
# Getting Started
## Requirements
- Node.js 20+
- pnpm 9+
## Install Dependencies
```bash
pnpm install
```
## Run Projects
```bash
# Run docs
pnpm --filter ./apps/docs dev
# Run basic template
pnpm --filter ./apps/basic dev
# Run Lingui template
pnpm --filter ./apps/with-lingui dev
```
## Build
```bash
pnpm --filter ./apps/basic build
pnpm --filter ./apps/with-lingui build
```
## Next Steps
- Scripts: [Available Scripts](/en/getting-started/available-scripts)
- Structure: [Folder Structure](/en/getting-started/folder-structure)
- Browser support: [Supported Browsers](/en/getting-started/supported-browsers)
@@ -0,0 +1,15 @@
---
title: Supported Browsers
description: Browser compatibility policy for this project
---
# Supported Browsers
This project targets modern evergreen browsers:
- Latest Chrome
- Latest Edge
- Latest Firefox
- Latest Safari
For old browser support requirements, evaluate and add polyfills case-by-case based on your user base.
@@ -0,0 +1,17 @@
---
title: Supported Features
description: Core features available in the templates
---
# Supported Features
The templates include:
- User login and permission-based routing
- Dashboard and reusable business pages
- Request abstraction and API proxy support
- Theme and layout customization
- Mock data support with MSW
- Unit tests and E2E tests
Feature details may vary slightly between `basic` and `with-lingui`.
@@ -0,0 +1,15 @@
---
title: Updating Releases
description: Recommendations for keeping your project up to date
---
# Updating Releases
To keep your project updated:
1. Pull the latest code from upstream.
2. Run `pnpm install` to refresh lockfile-resolved dependencies.
3. Verify with `build`, `lint`, and `test`.
4. Resolve breaking changes before releasing.
For production apps, perform updates on a branch and validate in CI before merging.
+16
View File
@@ -0,0 +1,16 @@
---
title: Overview
description: antd-admin monorepo and docs guide
---
# Overview
This repository provides two runnable admin templates: **[`apps/basic`](https://github.com/zuiidea/antd-admin/tree/master/apps/basic)** (English UI) and **[`apps/with-lingui`](https://github.com/zuiidea/antd-admin/tree/master/apps/with-lingui)** (Lingui-based bilingual UI).
The stack centers on **React 19, Ant Design 6, TanStack Router & Query, Vite+ (`vp`), MSW, and Playwright**.
The sidebar is organized as: Welcome → Getting Started → Templates → Development → Styles & Assets → Building → Testing → Backend Integration → Deployment.
Start from **[Getting Started](/en/getting-started)**, then choose a template in **[Templates](/en/templates)**.
GitHub: [zuiidea/antd-admin](https://github.com/zuiidea/antd-admin)
@@ -0,0 +1,8 @@
/** @type {import('nextra').MetaRecord} */
export default {
"code-splitting": "Code Splitting",
"css-modules": "CSS Modules",
"images-fonts-files": "Images, Fonts, and Files",
"public-folder": "Public Folder",
stylesheet: "Stylesheet",
};
@@ -0,0 +1,10 @@
---
title: Code Splitting
description: Reduce initial payload with route-level and module-level splitting
---
# Code Splitting
Apply code splitting for large routes and rarely used modules to improve first-load performance.
Use dynamic imports where appropriate and avoid loading heavy modules on initial render.
@@ -0,0 +1,10 @@
---
title: CSS Modules
description: Scoped styling strategy in the project
---
# CSS Modules
Use CSS Modules for component-scoped styles to reduce global style conflicts.
Adopt clear naming and keep styles colocated with the related component.
@@ -0,0 +1,10 @@
---
title: Images, Fonts, and Files
description: Best practices for static asset management
---
# Images, Fonts, and Files
Place static assets in predictable directories and reference them consistently.
For large files, consider CDN delivery and caching strategy to improve load performance.
@@ -0,0 +1,10 @@
---
title: Public Folder
description: How to use public assets in apps
---
# Public Folder
Use the public folder for static files that should be served directly.
Keep naming stable and avoid storing sensitive content in public assets.
@@ -0,0 +1,13 @@
---
title: Stylesheet
description: Organize global and component styles clearly
---
# Stylesheet
Keep a clear separation between:
- Global style tokens and resets
- Component-local styles
This helps maintain consistency and avoids accidental style leakage.
+6
View File
@@ -0,0 +1,6 @@
/** @type {import('nextra').MetaRecord} */
export default {
index: "Templates",
basic: "basic",
"with-lingui": "with-lingui",
};
+26
View File
@@ -0,0 +1,26 @@
---
title: basic
description: Lightweight admin template for single-language projects
---
# basic
`apps/basic` is a streamlined admin template focused on fast startup and simple extension.
## Good Fit
- Internal tools
- Small-to-medium dashboard projects
- Teams not requiring i18n yet
## Highlights
- Clean route organization
- Common data table and form patterns
- Practical defaults for request handling and page layout
## Start Development
```bash
pnpm --filter ./apps/basic dev
```
+16
View File
@@ -0,0 +1,16 @@
---
title: Templates
description: Choose between basic and with-lingui templates
---
# Templates
This repository provides two templates:
- **[basic](/en/templates/basic)**: Minimal setup, English UI by default.
- **[with-lingui](/en/templates/with-lingui)**: Includes Lingui i18n workflow and bilingual setup.
## How to Choose
- Choose **basic** if you only need one language.
- Choose **with-lingui** if you need structured multilingual support from day one.
@@ -0,0 +1,26 @@
---
title: with-lingui
description: Admin template with Lingui internationalization
---
# with-lingui
`apps/with-lingui` adds multilingual capabilities based on Lingui while keeping the same admin architecture.
## Good Fit
- Products serving multiple regions/languages
- Teams that want standardized translation workflow
- Projects requiring language switch in UI
## Highlights
- Lingui message extraction and compilation flow
- Language resource organization
- Built-in language switching patterns
## Start Development
```bash
pnpm --filter ./apps/with-lingui dev
```
+5
View File
@@ -0,0 +1,5 @@
/** @type {import('nextra').MetaRecord} */
export default {
"running-tests": "Running Tests",
"debugging-tests": "Debugging Tests",
};
@@ -0,0 +1,15 @@
---
title: Debugging Tests
description: Diagnose flaky or failing tests effectively
---
# Debugging Tests
When tests fail:
1. Reproduce locally with focused scope.
2. Inspect stack traces and assertions.
3. Isolate flaky dependencies (time, network, global state).
4. Stabilize with proper setup/teardown.
Prefer fixing root causes over adding retries.
@@ -0,0 +1,18 @@
---
title: Running Tests
description: Run unit and e2e tests in this repository
---
# Running Tests
Run tests from repository root or per app.
Common commands:
```bash
pnpm -r test
pnpm --filter ./apps/basic test
pnpm --filter ./apps/with-lingui test
```
Set up CI to run tests on pull requests before merge.
+4
View File
@@ -0,0 +1,4 @@
/** @type {import('nextra').MetaRecord} */
export default {
"documentation-intro": "Documentation Overview",
};
@@ -0,0 +1,24 @@
---
title: Documentation Overview
description: How to use this documentation and choose a project template
---
# Documentation Overview
The docs in this project are built with **Nextra + Next.js App Router**.
If this is your first time here:
1. Read **[Getting Started](/en/getting-started)** for setup and scripts.
2. Compare templates in **[Templates](/en/templates)**.
3. Go to **[Backend Integration](/en/backend/proxying-api-requests)** if you need API setup.
## Repo Structure
- `apps/basic`: English-only admin template
- `apps/with-lingui`: Internationalized template with Lingui
- `apps/docs`: Documentation site
## Recommended Reading Order
Welcome → Getting Started → Templates → Development → Building → Testing → Deployment
-1
View File
@@ -14,7 +14,6 @@ export default [
{
files: ["mdx-components.tsx"],
rules: {
// Nextra 主题在模块顶层合并默认 MDX 组件;与 `use*` 命名冲突于 hooks 规则,见 https://nextra.site/docs/file-conventions/mdx-components-file
"react-hooks/rules-of-hooks": "off",
},
},
+1 -1
View File
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+4
View File
@@ -6,4 +6,8 @@ const withNextra = nextra({
export default withNextra({
reactStrictMode: true,
i18n: {
locales: ["zh", "en"],
defaultLocale: "zh",
},
});
+1 -1
View File
@@ -6,7 +6,7 @@
"dev": "next dev -p 3003",
"build": "next build",
"start": "next start -p 3000",
"lint": "next lint"
"lint": "tsc --noEmit"
},
"dependencies": {
"next": "^16.2.4",
+6 -2
View File
@@ -1,5 +1,6 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { proxy as localeProxy } from "nextra/locales";
/**
* Browsers or other localhost apps (e.g. MSW) may request `/mockServiceWorker.js`.
@@ -18,9 +19,12 @@ export function proxy(request: NextRequest) {
},
);
}
return NextResponse.next();
return localeProxy(request);
}
export const config = {
matcher: "/mockServiceWorker.js",
matcher: [
"/mockServiceWorker.js",
"/((?!api|_next/static|_next/image|favicon.ico|icon.svg|apple-icon.png|manifest|_pagefind).*)",
],
};