Frontend Architecture (Base Project)
Module boundaries
src/views/*: page-level composition only.src/service/api/generated/*: official SDK generated by@hey-api/openapi-tsfrom backend OpenAPI.src/service/api/*: domain-level API facades that expose the stable app-facing API layer. Core admin endpoints should route through the generated SDK viagenerated-adapter.ts; only non-contract endpoints may fall back to directrequest(...).src/service/api/generated-adapter.ts: adapter that normalizes generated SDK responses into existing flat{ data, error }flow.src/store/modules/*: state and orchestration, no direct UI components.src/hooks/business/*: reusable page/business logic (CRUD, tenant switch, search).src/hooks/common/*: framework-level generic hooks.
Access-control flow
- Backend returns menu metadata + route rules.
- Route access is evaluated in
src/store/modules/route/auth-access.ts. - UI action visibility (
view/manage) is handled in page-level auth checks.
API contract workflow
- Frontend client snapshot:
docs/api-client-contract.snapshot - Frontend-to-backend compatibility allowlist:
docs/api-backend-compat.allowlist.json - Version compatibility matrix:
docs/compatibility-matrix.md - One-command generation:
npm run generate-api(remote-first OpenAPI input with local fallback) - Type generation source:
../obsidian-admin-laravel/docs/openapi.yaml../obsidian-admin-laravel/docs/api-contract.snapshot../obsidian-admin-laravel/app/DTOs../obsidian-admin-laravel/app/Http/Resources
Maintainability rules
- Keep page files thin by extracting repeated logic to hooks.
- Keep route authorization logic centralized in one module.
- Keep request models centralized in
src/typings/api/*. - CI must run lint, typecheck, unit test, and contract gates.
- Business code must not import the request entrypoint directly.
- Business code must not import the generated SDK directly; go through
src/service/api/*facades orsrc/service/api/generated-adapter.ts. src/service/api/route.tsis the current intentional exception because it targets template-local route endpoints, not the Laravel backend contract.- Keep delete/deactivate UX consistent via
docs/deletion-ui-guidelines.md. - API-backed forms must use the shared server-validation path:
useNaiveForm()- request config
handleValidationErrorLocally: true naiveForm.applyServerValidation(error)for field-level replay
Auth module truth
pwd-login,register, andreset-pwdare aligned with the current backend contract.code-loginremains a template-only placeholder until a real verification-code auth API is introduced.bind-wechatremains a placeholder until a real social-auth contract is introduced.
Scaffolding workflow
- Use
pnpm generate:pageto scaffold a standard code/name/status CRUD surface with two prompts:- resource key in singular kebab-case
- labels in
English / Chinese
- The generator creates:
src/views/<page>/index.vuesrc/views/<page>/modules/<page>-search.vuesrc/views/<page>/modules/<page>-operate-drawer.vuesrc/typings/api/<page>.d.tssrc/service/api/<page>.tstests/vue/<page>-operate-drawer.spec.ts
- It also appends:
- route i18n keys in
src/locales/langs/modules/en-us/route.tsandsrc/locales/langs/modules/zh-cn/route.ts - page i18n keys in
src/locales/langs/modules/en-us/page.tsandsrc/locales/langs/modules/zh-cn/page.ts - API export wiring in
src/service/api/index.ts
- route i18n keys in
- Post-generation it regenerates i18n typings and lint-fixes only the touched files.
- It deliberately does not call
pnpm gen-route; that command is reserved for Soybean route creation, not route manifest refresh.
Standard paginated CRUD hook
- Use
src/hooks/business/crud-paginated-table.tsas the default wrapper for list pages. - It standardizes:
- pagination sync (
current/size) - request param normalization
- loading state (
tableLoading) - optional initial data bootstrap with
useAsyncState - optional unified API error toast handling
- pagination sync (