diff --git a/README.md b/README.md index 39b57ab..2e3f5ba 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@
-Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. AI-friendly with clear patterns, shared abstractions, scoped AI instructions, and type-safe contracts at every boundary. +Balanced admin monorepo: MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. Ship either an **English-only** app (`apps/basic`) or a **Lingui i18n** variant (`apps/with-lingui`); see [Templates](#templates) below. [![antd](https://img.shields.io/badge/AntD-^6.0.0-1890ff?style=flat-square&logo=ant-design)](https://github.com/ant-design/ant-design) [![react](https://img.shields.io/badge/React-19.2-61dafb?style=flat-square&logo=react)](https://react.dev) @@ -31,7 +31,7 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and | Async State | [TanStack Query v5](https://tanstack.com/query) | | Local State | [Zustand](https://zustand.docs.pmnd.rs) (persisted auth & settings) | | Validation | [Zod v4](https://zod.dev) (schemas, API contracts, form validation) | -| i18n | [LinguiJS](https://lingui.dev) (en + zh catalogs) | +| i18n | [LinguiJS](https://lingui.dev) in **`apps/with-lingui` only** (`apps/basic` is English-only, no Lingui) | | Icons | [lucide-react](https://lucide.dev/guide/packages/lucide-react) | | API Mocking | [MSW 2.x](https://mswjs.io) (Service Worker based) | | E2E Testing | [Playwright](https://playwright.dev) | @@ -42,11 +42,32 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and - **JWT Authentication** — Login with access/refresh token flow, persisted via Zustand - **Dynamic Menu & RBAC** — Backend-driven sidebar menu with permission guards and 403 page - **URL-First State** — Table search params (page, pageSize, keyword, sort) synced to URL -- **i18n** — LinguiJS with English (`en`) and Chinese (`zh`); Ant Design locales wired in root +- **i18n (with-lingui app)** — LinguiJS with English (`en`) and Chinese (`zh`); Ant Design locales follow the active locale in `apps/with-lingui` - **Dark Mode** — One-click toggle with Ant Design theme algorithm - **Full Type Safety** — Zod schemas validate API boundaries at runtime where used - **Zero-Config Mocking** — MSW intercepts API calls in development, no backend needed +## Templates + +| Directory | Use when | +| -------------------- | -------- | +| [`apps/with-lingui`](./apps/with-lingui/) | You want **LinguiJS** (en + zh), `.po` extract/compile, and a language switcher — this is the fuller reference stack. | +| [`apps/basic`](./apps/basic/) | You want the **same product surface** with **English-only** UI (no Lingui, fixed `en_US` for Ant Design). | + +Pick one app directory, install, and run Vite+ from there: + +```bash +cd apps/basic && vp install && vp dev +# or +cd apps/with-lingui && vp install && vp dev +``` + +Core Playwright flows (from the app you are working in): + +```bash +cd apps/basic && pnpm run test:e2e:core +``` + ## Getting Started ### Prerequisites @@ -56,7 +77,10 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and ### Install & Run +From the repository root, choose an app under `apps/` (see [Templates](#templates)), then: + ```bash +cd apps/with-lingui # or: cd apps/basic vp install vp dev ``` @@ -74,10 +98,13 @@ vp preview ### E2E Tests +Run from the app package (example: `apps/basic`): + ```bash -vp run test:e2e -vp run test:e2e:core -vp run test:e2e:ui # interactive UI mode +cd apps/basic +pnpm run test:e2e +pnpm run test:e2e:core +pnpm run test:e2e:ui # interactive UI mode ``` `test:e2e:core` runs the scaffold's highest-value flows only: login and users CRUD. diff --git a/apps/basic/README.md b/apps/basic/README.md index ee2a31e..c107c20 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -8,7 +8,7 @@
-Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. AI-friendly with clear patterns, shared abstractions, scoped AI instructions, and type-safe contracts at every boundary. +English-only admin scaffold (no Lingui): MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. For Lingui-based i18n (en + zh), use the sibling app [`apps/with-lingui`](../with-lingui/). [![antd](https://img.shields.io/badge/AntD-^6.0.0-1890ff?style=flat-square&logo=ant-design)](https://github.com/ant-design/ant-design) [![react](https://img.shields.io/badge/React-19.2-61dafb?style=flat-square&logo=react)](https://react.dev) @@ -31,7 +31,7 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and | Async State | [TanStack Query v5](https://tanstack.com/query) | | Local State | [Zustand](https://zustand.docs.pmnd.rs) (persisted auth & settings) | | Validation | [Zod v4](https://zod.dev) (schemas, API contracts, form validation) | -| i18n | [LinguiJS](https://lingui.dev) (en + zh catalogs) | +| UI language | English strings in source (no i18n framework) | | Icons | [lucide-react](https://lucide.dev/guide/packages/lucide-react) | | API Mocking | [MSW 2.x](https://mswjs.io) (Service Worker based) | | E2E Testing | [Playwright](https://playwright.dev) | @@ -42,7 +42,7 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and - **JWT Authentication** — Login with access/refresh token flow, persisted via Zustand - **Dynamic Menu & RBAC** — Backend-driven sidebar menu with permission guards and 403 page - **URL-First State** — Table search params (page, pageSize, keyword, sort) synced to URL -- **i18n** — LinguiJS with English (`en`) and Chinese (`zh`); Ant Design locales wired in root +- **English-only** — No Lingui or locale catalogs; Ant Design uses a fixed `en_US` locale. See [`apps/with-lingui`](../with-lingui/) for bilingual LinguiJS. - **Dark Mode** — One-click toggle with Ant Design theme algorithm - **Full Type Safety** — Zod schemas validate API boundaries at runtime where used - **Zero-Config Mocking** — MSW intercepts API calls in development, no backend needed @@ -56,7 +56,10 @@ Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and ### Install & Run +From the monorepo root, or after `cd apps/basic`: + ```bash +cd apps/basic vp install vp dev ``` @@ -75,9 +78,10 @@ vp preview ### E2E Tests ```bash -vp run test:e2e -vp run test:e2e:core -vp run test:e2e:ui # interactive UI mode +cd apps/basic +pnpm run test:e2e +pnpm run test:e2e:core +pnpm run test:e2e:ui # interactive UI mode ``` `test:e2e:core` runs the scaffold's highest-value flows only: login and users CRUD. @@ -111,9 +115,6 @@ src/ ├── utils/ │ ├── constants.ts # API base URL, static assets │ └── http.ts # HTTP client with JWT injection & error handling -├── locales/ # LinguiJS catalogs (.po + compiled .js) -│ ├── en/messages.po -│ └── zh/messages.po ├── mocks/ │ ├── browser.ts # MSW worker setup │ ├── createHandler.ts # Shared MSW success/error/delay helpers @@ -121,7 +122,7 @@ src/ │ ├── utils.ts # Mock-only helpers (filters, pagination, demo avatar URLs) │ └── handlers/ # Request handlers (auth, user CRUD) ├── routes/ # TanStack Router file-based routes -│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, I18n) +│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, en_US) │ ├── _auth.tsx # Auth guard layout (redirects to /login) │ ├── _auth/dashboard/index.tsx │ ├── _auth/users/index.tsx # Full CRUD with URL-synced search params @@ -132,33 +133,25 @@ src/ ├── stores/ │ ├── auth.ts # Auth store (tokens, user, menus, permissions) │ ├── createPersistentStore.ts # Shared persisted-store factory -│ └── settings.ts # Settings store (darkMode, locale, sidebar) +│ └── settings.ts # Settings store (darkMode, sidebar) └── main.tsx # Entry point (MSW init → React render) -tests/ -└── e2e/ # Playwright E2E tests - ├── helpers.ts - ├── login.spec.ts - └── users.spec.ts +e2e/ # Playwright E2E tests +├── helpers.ts +├── login.spec.ts +└── users.spec.ts ``` -## Internationalization (i18n) +## Language & i18n -The project uses [LinguiJS](https://lingui.dev) with compile-time macros. Locales: `**en**` (source) and `**zh**`. +This template is **English-only**: user-facing copy lives in components and routes as plain strings; there is no Lingui catalog or language switcher. -### Workflow - -```bash -vp run i18n:extract -vp run i18n:compile -``` - -Ant Design strings follow the active locale via `ConfigProvider` in `__root.tsx`. +For **LinguiJS** (English + Chinese, `.po` extract/compile, and Ant Design locale switching), use [`apps/with-lingui`](../with-lingui/). ## Extending the template - **Real backend:** Point `VITE_API_BASE_URL` in env and disable or remove MSW in `main.tsx` when you no longer need mocks. -- **Drop i18n:** Remove Lingui packages, vite/swc plugins, and replace `t` macros with plain strings (larger refactor). +- **Add i18n:** Start from [`apps/with-lingui`](../with-lingui/) or port Lingui setup from that app; this `basic` tree intentionally omits it. ## Developer Notes diff --git a/apps/basic/package.json b/apps/basic/package.json index 851d4c4..be722d3 100644 --- a/apps/basic/package.json +++ b/apps/basic/package.json @@ -12,7 +12,7 @@ "lint": "vp lint", "check": "vp check --no-fmt", "test:e2e": "playwright test", - "test:e2e:core": "playwright test tests/e2e/login.spec.ts tests/e2e/users.spec.ts", + "test:e2e:core": "playwright test e2e/login.spec.ts e2e/users.spec.ts", "test:e2e:ui": "playwright test --ui" }, "dependencies": { diff --git a/apps/basic/playwright.config.ts b/apps/basic/playwright.config.ts index b04afbf..4f095ca 100644 --- a/apps/basic/playwright.config.ts +++ b/apps/basic/playwright.config.ts @@ -6,7 +6,7 @@ declare const process: { env: { CI?: string } }; const ci = Boolean(process.env.CI); export default defineConfig({ - testDir: "./tests/e2e", + testDir: "./e2e", fullyParallel: true, forbidOnly: ci, retries: ci ? 2 : 0,