The mibudge SPA is a Vue 3 + TypeScript single-page app in frontend/.
Django serves it at /app/*, and Vue Router handles every sub-route. It
talks to the backend only through the versioned REST API (/api/v1/)
and the JWT endpoints (/api/token/...). It keeps the access token in
memory and uses Pinia stores for the session, the active account and
cached domain data.
The source is split into layers (domain → api/models → stores and
composables → features → components and views), each allowed to import
only from the layers below it. Start with Architecture.
frontend/README.md covers the commands and the Vite and Django
integration.
| Document | Purpose |
|---|---|
| Architecture | The layers, what each may import, naming, the request lifecycle (401 refresh, AuthError), the router (typed names, meta.access and the guard, cold boot), how sections communicate |
| API and models | The HTTP transport, ApiError, regenerating API types, DTOs vs models, money and date rules, adding a REST resource |
| State | Each Pinia store, caching and invalidation, settings that save on change (useOptimistic), the sign-out reset, store vs composable vs local state |
| Adding a page | Recipe and worked example for a new route; rewriting an existing view incrementally |
| Components | Presentational vs feature components, props / emits / defineModel, naming |
| Styling | The design system: tokens, type roles, the Base* primitives, the style lint, and how to change a style |
| Screens | What each screen shows and does, the app shell and navigation, and the conventions every screen shares |
| Testing | Running and writing SPA tests: Vitest, the MSW mock REST API, fixtures, coverage, CI |
Later SPA documents add their own row to this table.
These documents move with frontend/ if the SPA becomes its own
repository, so they link only to each other, into frontend/, and to
the REST API contract (docs/openapi.yaml and docs/api.md).
Things the SPA does not do yet, each with the document that covers the current behaviour:
DISPLAY_FORMAT (domain/displayFormat.ts), which names the locale
(styling.md).docs/openapi.yaml, so their DTOs are taken from
inline operation types or written by hand in api/dto.ts
(api-and-models.md).