website refactor
This commit is contained in:
@@ -11,6 +11,13 @@ In this codebase, a Display is a **Frontend Value Object**:
|
||||
- deterministic
|
||||
- side-effect free
|
||||
|
||||
### Distinction from Domain Value Objects
|
||||
|
||||
While both are "Value Objects", they serve different layers:
|
||||
|
||||
1. **Domain Value Objects (Core):** Encapsulate business truth and invariants (e.g., `Money`, `EmailAddress`). They are pure and never contain formatting logic.
|
||||
2. **Display Objects (Website):** Encapsulate presentation truth and formatting (e.g., `PriceDisplay`, `DateDisplay`). They are used to transform raw data or Domain Value Objects into user-ready strings.
|
||||
|
||||
It answers the question:
|
||||
|
||||
> “How should this specific piece of information be shown?”
|
||||
@@ -65,6 +72,8 @@ A Display MUST NOT:
|
||||
- influence system behavior
|
||||
- be sent back to the server
|
||||
- depend on backend or infrastructure concerns
|
||||
- **depend on environment-specific APIs** (e.g., `window`, `document`, `navigator`)
|
||||
- **be serialized** (they are classes; only their primitive outputs are stored in `ViewData`)
|
||||
|
||||
In this repository, a Display MUST NOT:
|
||||
|
||||
@@ -73,6 +82,25 @@ In this repository, a Display MUST NOT:
|
||||
|
||||
Reason: these are runtime-locale/timezone dependent and cause SSR/hydration mismatches.
|
||||
|
||||
### Handling Client-Only Formatting
|
||||
|
||||
If a formatting requirement **strictly requires** client-only APIs (e.g., browser-native relative time or local timezone detection):
|
||||
|
||||
1. It MUST NOT live in a `Display Object`.
|
||||
2. It SHOULD live in a **View Model** (which is client-only).
|
||||
3. The Template should handle the transition from server-provided `ViewData` to client-updated `ViewData`.
|
||||
|
||||
### Best Practices for Time/Date Formatting
|
||||
|
||||
To avoid hydration mismatches while still providing good SEO and UX:
|
||||
|
||||
1. **Use UTC methods for Determinism:** In `Display Objects`, prefer `getUTCDate()`, `getUTCMonth()`, etc., over their local counterparts. This ensures the server and client produce the exact same string regardless of their local timezones.
|
||||
2. **Hardcoded Arrays:** Use hardcoded arrays for month/day names instead of `Intl` to ensure consistency across environments.
|
||||
3. **Pass "Now" as an Argument:** For relative time (e.g., "time ago"), pass the reference "now" timestamp as an argument to the `Display Object` instead of calling `Date.now()` inside it.
|
||||
4. **The "Upgrade" Pattern:**
|
||||
- **Server:** `ViewData Builder` uses a `Display Object` to produce a deterministic UTC-based string (e.g., "2024-01-18 15:00 UTC").
|
||||
- **Client:** `View Model` uses client APIs (`Intl`, `toLocale*`) to produce a localized string (e.g., "3:00 PM") and updates the `ViewData`.
|
||||
|
||||
## Localization rule (strict)
|
||||
|
||||
Localization MUST NOT depend on runtime locale APIs.
|
||||
@@ -105,16 +133,17 @@ Placement rule (strict):
|
||||
|
||||
---
|
||||
|
||||
## Relationship to View Models
|
||||
## Relationship to View Models and ViewData Builders
|
||||
|
||||
- View Models MAY use Displays
|
||||
- Displays MUST NOT depend on View Models
|
||||
- Displays represent **parts**
|
||||
- View Models represent **screens**
|
||||
Displays are the **shared source of truth** for formatting logic across the website:
|
||||
|
||||
- **ViewData Builders (Server):** Use Displays to produce deterministic, formatted strings for SEO and initial SSR.
|
||||
- **View Models (Client):** Use Displays to produce formatted strings for interactive UI and client-specific context.
|
||||
|
||||
Additional strict rules:
|
||||
|
||||
- View Models SHOULD compose Displays.
|
||||
- ViewData Builders SHOULD use Displays for all formatting.
|
||||
- Displays MUST NOT be serialized or passed across boundaries.
|
||||
- They must not appear in server-to-client DTOs.
|
||||
- Templates should receive primitive display outputs, not Display instances.
|
||||
@@ -138,9 +167,17 @@ Additionally:
|
||||
|
||||
## Summary
|
||||
|
||||
- Displays encapsulate **how something looks**
|
||||
- View Models encapsulate **what a screen needs**
|
||||
- Both are presentation concerns
|
||||
- Neither contains business truth
|
||||
- Displays encapsulate **how something looks** (the single source of truth for formatting logic).
|
||||
- View Models encapsulate **what a screen needs** (including client-specific "last mile" formatting).
|
||||
- Both are presentation concerns.
|
||||
- Neither contains business truth.
|
||||
|
||||
In one sentence: Displays are **Value Objects for UI display**, not utility functions.
|
||||
In one sentence: **Displays are the shared source of truth for deterministic formatting logic, used by both the server and the client.**
|
||||
|
||||
---
|
||||
|
||||
## Final Rule: Where does formatting go?
|
||||
|
||||
1. **Is it deterministic?** (e.g., currency symbols, fixed date formats, labels) → **Display Object**.
|
||||
2. **Is it client-only?** (e.g., `Intl.*`, `toLocale*`, browser timezone) → **View Model**.
|
||||
3. **Is it for SEO?** → **ViewData Builder** (using a Display Object).
|
||||
Reference in New Issue
Block a user