docs(form-schema): document shared package boundary and tech debt

Documents the "share schema, not UI" principle in dev-guide.md so the
boundary stays intact in future work. Logs TECH-DEBT-01 for the
@core/utils/validators transitive dependency discovered during PR-a.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 00:04:41 +02:00
parent dda60ed5e4
commit 42dd626e37
2 changed files with 57 additions and 0 deletions

View File

@@ -381,6 +381,47 @@ Altijd in deze volgorde. Nooit stappen overslaan — later toevoegen kost meer t
| Fase 3 — Advancing & Show Day | Artist advancing + portaal, Timetable, Mission Control, Formulierbouwer, Post-festival evaluatie, PDF allocatiesheet, Campagnes (email + WhatsApp via Zender) |
| Fase 4 — Differentiators | Real-time WebSockets, Show Day Mode, Vrijwilligersprofiel + festival-paspoort, Shift swap & wachtlijst, Retrospectief rapport, Leveranciersportaal uitgebreid |
## Shared frontend packages
`apps/portal/` en `apps/app/` delen een klein aantal schema-gedreven modules. Deze sectie legt vast wat wel en niet in die gedeelde laag hoort, en hoe je de aliases opzet.
### Locatie
`packages/form-schema/` — pure TypeScript, **geen** `package.json`, alias-only. Geen npm-package en geen pnpm workspace member; puur geconsumeerd via per-app TypeScript- en Vite-path-aliases.
### Wat hoort erin
- Schema-types die backend PHP-enums en API-resources mirroren (bv. `PublicFormField`, `FormFieldType`, `PublicFormSchema`)
- Schema-gedreven gedrag: validation rule builders, conditional-logic evaluator, step-navigation, stored-value formatters
- Alles wat pure TypeScript is en in portal én app exact dezelfde output moet produceren
### Wat hoort er NIET in
- Vue SFCs (`.vue` bestanden) — elke app rendert zijn eigen UI
- Vuetify/Vuexy-specifieke code, theming of styling
- Vue Router-code, route-definities of navigation guards
- Pinia stores of app-level state
- Axios-instanties of API-client code
- Composables die afhangen van app-runtime (auth, i18n, router)
### Rationale
Portal is submit-facing, app is builder- en review-facing. De twee apps zullen visueel uit elkaar groeien naarmate product-requirements verschillen. Gedeelde Vue-componenten zouden hun stijlen aan elkaar koppelen — daarom delen we het *contract en de logica* (schema-types, gedrag) maar laat elke app zijn eigen UI bezitten.
### Alias-setup (verplicht op drie plekken per app)
Beide apps moeten `@form-schema/*` registreren in álle drie:
- `apps/<app>/tsconfig.json``compilerOptions.paths`
- `apps/<app>/vite.config.ts``resolve.alias`
- `apps/<app>/vitest.config.ts``resolve.alias`
Alle drie zijn nodig omdat `vitest.config.ts` niet overerft van `vite.config.ts`. Eén van de drie vergeten breekt óf de productie-build, óf de dev-server, óf de test-suite. Wanneer een derde app consumer wordt, wire dan alle drie tegelijk.
### Vue-resolutie (dependency-note)
Het gedeelde package heeft geen `package.json` en kan dus geen eigen dependencies declareren. Om `vue` resolvable te maken tijdens TypeScript-compilatie vanuit `packages/form-schema/src/`, voegen beide apps een `"vue": ["./node_modules/vue"]`-entry toe aan `compilerOptions.paths`. Dit is het minimum; als het package ooit niet-triviale externe imports krijgt (bv. `@vueuse/core`, `lodash`), voeg dan per app een vergelijkbare paths-entry toe — níet een `package.json` in het package — of promoveer het package tot workspace-member.
## 5. Prompt Bibliotheek
Kant-en-klare prompts voor elke ontwikkelstap