# View Models ## Definition A **View Model** represents a **fully prepared UI state**. It answers the question: > “What does the UI need in order to render this screen without thinking?” View Models are **UI-owned** classes. They do not represent business truth and do not enforce domain rules. **Uncle Bob says**: "Objects expose behavior, not data." ViewModels encapsulate the behavior of the UI. --- ## Responsibilities A View Model MAY: - accept an API DTO as input - derive UI-specific fields - combine or reshape data for rendering - perform formatting (dates, numbers, labels), especially for **client-only context** (e.g., local timezone, relative "time ago") - handle localization and presentation logic - use **Display Objects** for reusable UI concerns and rich APIs ### Formatting Responsibility While `ViewData Builders` handle formatting for SEO and initial render using **Formatters**, `View Models` are responsible for: - **Client-specific formatting:** Data that depends on the browser's locale, timezone, or precise location. - **Interactive formatting:** Updating display values in response to user input or state changes. - **Rich APIs:** Providing **Display Objects** to the UI for multi-variant formatting (e.g., `date.short`, `date.relative`). In the website SSR/RSC architecture, View Models MAY compute view-only derived values, but MUST NOT be the type passed into Templates. A View Model MUST: - be fully usable by the UI without further computation - expose only data and UI-oriented helpers - be created in a consistent, explicit way --- ## Restrictions A View Model MUST NOT: - contain business logic - validate domain rules - enforce permissions or authorization - contain domain entities or value objects - perform side effects - be sent back to the server If a View Model decides whether something is *allowed* or *correct*, that logic belongs in the Core, not here. --- ## Ownership & Placement - View Models belong to the **frontend** - They live close to the UI, not in shared or core layers - They are not shared with the backend --- ## Creation Rules This repository distinguishes **Page DTO**, **ViewModel**, and **ViewData**: - Page DTO: server-to-client payload (JSON-serializable) - ViewModel: client-only class (never serialized) - ViewData: template input (JSON-serializable) Rules (website): 1) View Models are created in client code only. 2) View Models are created from **ViewData** (not from DTOs). 3) Templates MUST NOT accept View Models; Templates accept ViewData only. 4) View Models MUST compose Display Objects and produce rich UI APIs. Authoritative reference: [plans/nextjs-rsc-viewmodels-concept.md](plans/nextjs-rsc-viewmodels-concept.md:1). --- ## Testing View Models SHOULD be tested when they contain: - formatting logic - localization behavior - non-trivial derived fields View Models do NOT need tests if they only expose data without logic. --- ## Summary - View Models describe **UI state** - They are **presentation-focused**, not business-focused - They reduce complexity in components - They form a stable contract for the UI