Files
gridpilot.gg/docs/architecture/website/VIEW_DATA.md
Marc Mintel 18133aef4c
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m42s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data fixes
2026-01-22 23:40:38 +01:00

94 lines
3.0 KiB
Markdown

# ViewData (Website Templates)
ViewData is the **only** allowed input type for Templates in `apps/website`.
Authoritative contract: [`WEBSITE_CONTRACT.md`](docs/architecture/website/WEBSITE_CONTRACT.md:1).
## 1) Definition
ViewData is a JSON-serializable, template-ready data structure:
- primitives (strings/numbers/booleans)
- arrays and plain objects
- `null` for missing values
## 2) What ViewData is NOT
ViewData is not:
- an API Transport DTO (raw transport)
- a ViewModel (client-only class)
- a Display Object instance
## 3) Construction rules
ViewData is created by **ViewData Builders**:
### Server Components (RSC)
```typescript
const apiDto = await PageQuery.execute();
const viewData = ViewDataBuilder.build(apiDto);
return <Template viewData={viewData} />;
```
### Client Components
```typescript
'use client';
const [viewModel, setViewModel] = useState<ViewModel | null>(null);
useEffect(() => {
const apiDto = await apiClient.get();
const viewData = ViewDataBuilder.build(apiDto);
const vm = ViewModelBuilder.build(viewData);
setViewModel(vm);
}, []);
// Template receives ViewData directly
return viewModel ? <Template viewData={viewData} /> : null;
```
Templates MUST NOT compute derived values.
ViewData Builders MUST NOT call the API.
**Important:** ViewModels are built from ViewData, not directly from DTOs. This ensures ViewModels are decoupled from the API transport layer.
## 4) Formatting and SEO
ViewData is responsible for providing **fully formatted strings** to Templates for Server-Side Rendering (SSR).
- **SEO Requirement:** All data required for search engines (prices, dates, counts, labels) MUST be formatted in the `ViewData Builder` on the server.
- **Template Simplicity:** Templates should simply render the strings provided in `ViewData` without further processing.
## 5) Determinism rules
Any formatting used to produce ViewData MUST be deterministic.
Forbidden anywhere in formatting code paths:
- `Intl.*`
- `Date.toLocaleString()` / `Date.toLocaleDateString()` / `Date.toLocaleTimeString()`
Reason: SSR and browser outputs can differ.
Localization MUST NOT depend on runtime locale APIs.
If localized strings are required, they MUST be provided as deterministic inputs (for example via API-provided labels or a deterministic code-to-label map) and passed through ViewData Builders into ViewData.
## 5) Relationship to ViewModels
ViewData serves as the stable, serializable contract between the server and client. It is:
- The input for Templates (both SSR and Client)
- The input for ViewModelBuilders (Client-side state initialization)
ViewModels are built from ViewData, not from DTOs. This ensures:
- ViewModels remain decoupled from API transport concerns
- ViewModels can be initialized from any source that provides ViewData
- The ViewModel layer is purely for client-side interactive state
## 6) Relationship to Display Objects
Display Objects are used to implement formatting/mapping, but their instances MUST NOT be stored inside ViewData.
Only primitive outputs produced by Display Objects may appear in ViewData.