Skip to content

Frontend Architecture (Base Project)

Module boundaries

  • src/views/*: page-level composition only.
  • src/service/api/generated/*: official SDK generated by @hey-api/openapi-ts from 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 via generated-adapter.ts; only non-contract endpoints may fall back to direct request(...).
  • 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 or src/service/api/generated-adapter.ts.
  • src/service/api/route.ts is 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, and reset-pwd are aligned with the current backend contract.
  • code-login remains a template-only placeholder until a real verification-code auth API is introduced.
  • bind-wechat remains a placeholder until a real social-auth contract is introduced.

Scaffolding workflow

  • Use pnpm generate:page to 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.vue
    • src/views/<page>/modules/<page>-search.vue
    • src/views/<page>/modules/<page>-operate-drawer.vue
    • src/typings/api/<page>.d.ts
    • src/service/api/<page>.ts
    • tests/vue/<page>-operate-drawer.spec.ts
  • It also appends:
    • route i18n keys in src/locales/langs/modules/en-us/route.ts and src/locales/langs/modules/zh-cn/route.ts
    • page i18n keys in src/locales/langs/modules/en-us/page.ts and src/locales/langs/modules/zh-cn/page.ts
    • API export wiring in src/service/api/index.ts
  • 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.ts as 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