Problem
The frontend currently runs three coexisting structures: legacy /store (Vuex), /v1 (DDD with DI, repositories, use-cases, view-models), and ad-hoc /components and /pages. There's no written rule for where new code goes, and the DDD pattern in /v1 is heavy (DI registry hop, class entities, view-model files) which is poor ergonomics for both human and agentic contributors.
Decision (to be documented)
- Vuex and Pinia both stay. No big-bang migration.
- New work goes in
extralit-frontend/src/features/<name>/ using a flat, feature-sliced layout:
api.ts — axios calls + zod parsing, returns plain objects
store.ts — Pinia store; state + actions, calls api.ts
types.ts — types (eventually generated from OpenAPI)
components/, composables/ — feature-local
- Shared cross-feature code lives in
src/shared/{api,ui,composables,types}.
/v1 and /store are frozen — no new files. Migrate via strangler when a feature is touched substantively.
- Banned in
features/: DI containers (useResolve), class-wrapped entities, separate useXxxViewModel.ts files, cross-feature imports.
Deliverable
A 1–2 page extralit-frontend/ARCHITECTURE.md covering: rationale, folder layout, the rules above, examples of "where does X go?", and the strangler migration policy.
Acceptance criteria
ARCHITECTURE.md merged.
CONTRIBUTING.md links to it.
- Reviewed by at least one frontend maintainer.
Problem
The frontend currently runs three coexisting structures: legacy
/store(Vuex),/v1(DDD with DI, repositories, use-cases, view-models), and ad-hoc/componentsand/pages. There's no written rule for where new code goes, and the DDD pattern in/v1is heavy (DI registry hop, class entities, view-model files) which is poor ergonomics for both human and agentic contributors.Decision (to be documented)
extralit-frontend/src/features/<name>/using a flat, feature-sliced layout:api.ts— axios calls + zod parsing, returns plain objectsstore.ts— Pinia store; state + actions, callsapi.tstypes.ts— types (eventually generated from OpenAPI)components/,composables/— feature-localsrc/shared/{api,ui,composables,types}./v1and/storeare frozen — no new files. Migrate via strangler when a feature is touched substantively.features/: DI containers (useResolve), class-wrapped entities, separateuseXxxViewModel.tsfiles, cross-feature imports.Deliverable
A 1–2 page
extralit-frontend/ARCHITECTURE.mdcovering: rationale, folder layout, the rules above, examples of "where does X go?", and the strangler migration policy.Acceptance criteria
ARCHITECTURE.mdmerged.CONTRIBUTING.mdlinks to it.