The frontend is a Yarn 4 monorepo. Day-to-day work is a small, fixed set of commands that run across every workspace at once. Before a commit lands, Husky + lint-staged format and lint the staged files, and commitlint enforces Conventional Commits.
UI slices also follow Page Development and
Design System 1.2. yarn scaffold:page, yarn dev:ui, and
yarn ui:check are future target commands, not currently available scripts.
1. Install
cd frontend
# strict install against the lockfile — fails if yarn.lock is out of syncyarn install --immutableYarn 4.17.0 is pinned via the packageManager field, and the release is vendored at .yarn/releases/yarn-4.17.0.cjs, so the correct version is used without a global install. .yarnrc.yml sets nodeLinker: node-modules (classic on-disk modules, not PnP) and npmRegistryServer: https://registry.npmmirror.com/ (the China npm mirror).
2. Workspace-wide scripts
These run from the frontend/ root and fan out to every workspace via yarn workspaces foreach -A:
# Verify dependencies before static, type, build, and formatting tasks.yarn install --immutable # strict installyarn lint # yarn workspaces foreach -A run lintyarn typecheck # yarn workspaces foreach -A run typecheckyarn build # yarn workspaces foreach -A run buildyarn format # prettier --write .The build script is not uniform across workspaces — know the difference:
| Workspace | build does |
|---|---|
packages (@bitz/*) | tsc --noEmit |
@bitz/app | tsc --noEmit && vite build |
@bitz/app-mobile | yarn build:h5 (Taro, not tsc) |
So yarn build from the root is a full typecheck (packages + web app) plus the web bundle and the mobile H5 bundle. To target a single workspace, use Yarn’s workspace selector:
yarn workspace @bitz/app build # just the web appyarn workspace @bitz/app-mobile build # just the mobile shell (H5)yarn workspace @bitz/platform-sdk build # just the SDK packageThe root package.json also wires mobile conveniences: yarn dev, yarn dev:mobile, yarn dev:mobile:weapp, yarn dev:mobile:harmony, yarn build:mobile:android, yarn build:mobile:ios, yarn build:mobile:harmony, yarn mobile:android:open, yarn mobile:ios:open. See Mobile shell for what each produces.
3. Regenerate the backend client
# backend emits the artifact (run first)scripts/build/export-openapi.sh # → artifacts/openapi/openapi-v1.json
# regenerate client types — note THREE ../ from packages/platform-sdk to repo rootyarn workspace @bitz/platform-sdk generate-client# → openapi-typescript ../../../artifacts/openapi/openapi-v1.json \# -o src/client/generated.d.ts
# guard against silent drift on CIscripts/build/check-openapi-drift.shAfter regeneration, yarn typecheck surfaces every call site that referenced a changed DTO. Do not hide those errors behind a hand-written interface; fix the call site or deliberately update the schema alias.
4. Commit conventions
Commits follow Conventional Commits, enforced by commitlint with @commitlint/config-conventional:
<type>(<scope>): <subject>typeis one of the conventional set (feat,fix,docs,refactor,test,chore, …).- Chinese subjects are permitted — commitlint does not require ASCII.
scopeis optional but encouraged for monorepo clarity (e.g.feat(platform-sdk): …).
Husky runs two hooks:
- commit-msg →
yarn commitlint --edit "$1" - pre-commit →
yarn lint-staged
lint-staged formats staged files with Prettier and lints staged *.{ts,tsx} with ESLint --fix. A failure blocks the commit.
{ "*.{js,cjs,mjs,ts,tsx,json,md,css}": ["prettier --write"], "*.{ts,tsx}": ["eslint --fix"]}Prettier config (prettier.config.cjs): singleQuote: true, semi: true, trailingComma: 'all', printWidth: 100. ESLint (eslint.config.js, flat config) extends @eslint/js recommended + typescript-eslint recommended; the only two custom rules are @typescript-eslint/no-explicit-any: 'off' and no-unused-vars (warn, ignore ^_ args). There is no import-boundary or jsx-a11y enforcement today.
5. Pre-commit expectations
Before a change is ready to push, all four must pass:
# Keep the local pre-push gate aligned with CI.yarn install --immutableyarn lintyarn typecheckyarn buildThese mirror the CI gate. yarn build includes a tsc --noEmit per workspace (except mobile, which builds via Taro), so type errors fail the build before bundling.
6. Testing
Only three packages have a test script today, all using Vitest (vitest run / watch via vitest):
| Package | Has test? | Notable test files |
|---|---|---|
@bitz/widgets | yes | server-data-table.test.tsx, app-shell.test.tsx, permission-gate.test.tsx |
@bitz/platform-sdk | yes | auth-session.test.ts, app-error.test.ts, api.test.ts, contracts.test.ts |
@bitz/i18n | yes | (vitest) |
@bitz/components, editor, hooks, utils, materials, scripts | no | — |
Architecture drift between the frontend and the backend is guarded by scripts/build/check-openapi-drift.sh, not by a frontend test.
7. Devtools
- Locator (web, dev-only):
@rolldown/plugin-babel+@locator/babel-jsxinservemode, plussetupLocatorUI()inmain.tsxwhenNODE_ENV === 'development'. ⌥-click any element to open its source. - TailwindInspector: a
@bitz/widgetsdebug component (rendered on thehomeroute) that inspects Tailwind classes on hover. Re-exported viaexport *from the widgets barrel.
8. What not to commit
The frontend .gitignore (and the subtree import) already exclude these — keep it that way:
node_modules/dist/,build/.yarn/cache(Yarn 4 withnode-moduleslinker does not need it in git)- native platform build output (
android/,ios/,harmony/) - IDE files and secrets
9. Reviewing a contributor change
- Confirm
yarn install --immutablesucceeds — the lockfile is in sync. - Confirm
yarn lint,yarn typecheck, andyarn buildall pass. - If the backend contract changed, export OpenAPI, regenerate the client, and fix affected call sites; never copy DTO fields.
- Confirm the commit message is Conventional Commits compliant (Chinese subject allowed).
- If a new dependency was added, confirm it is in the correct workspace’s
package.json, not the root unless it is truly shared.
10. Source review
# Confirm the pinned toolchain and workspace scripts.sed -n '1,60p' frontend/package.jsoncat frontend/commitlint.config.cjscat frontend/.yarnrc.ymlls frontend/.husky
# Confirm which packages actually have a test script.rg -n '"test"' frontend/packages/*/package.json