Files
gridpilot.gg/docs/architecture/website/DISPLAY_OBJECTS.md
2026-01-13 01:36:27 +01:00

3.6 KiB

Displays

Definition

A Display encapsulates reusable, UI-only display logic.

In this codebase, a Display is a Frontend Value Object:

  • class-based
  • immutable
  • deterministic
  • side-effect free

It answers the question:

“How should this specific piece of information be shown?”

Displays are not screen-specific. They exist to avoid duplicating presentation logic across View Models.

Naming Convention:

  • Displays MUST end with Display suffix
  • Displays MUST be reusable across multiple screens
  • Valid examples: PriceDisplay, EmailDisplay, RatingDisplay
  • Invalid examples: DashboardRatingDisplay, UserProfileDisplay

Responsibilities

A Display MAY:

  • format values (money, dates, durations)
  • handle localization only when localization inputs are deterministic (for example: mapping stable codes to stable labels)
  • map codes to labels
  • encapsulate UI display conventions
  • be reused across multiple View Models

In addition, a Display MAY:

  • normalize presentation inputs (for example trimming/casing)
  • expose multiple explicit display variants (for example shortLabel, longLabel)

A Display MUST:

  • be deterministic
  • be side-effect free
  • operate only on presentation data

A Display MUST:

  • be implemented as a class with a small, explicit API
  • accept only primitives/plain data in its constructor (or static factory)
  • expose only primitive outputs (strings/numbers/booleans)

Restrictions

A Display MUST NOT:

  • contain business logic
  • enforce domain invariants
  • perform validation
  • influence system behavior
  • be sent back to the server
  • depend on backend or infrastructure concerns

In this repository, a Display MUST NOT:

  • call Intl.*
  • call Date.toLocaleString() / Date.toLocaleDateString() / Date.toLocaleTimeString()

Reason: these are runtime-locale/timezone dependent and cause SSR/hydration mismatches.

Localization rule (strict)

Localization MUST NOT depend on runtime locale APIs.

Allowed approaches:

  • API returns the exact labels/strings for the current user context.
  • Website maps stable codes to stable labels using a deterministic table.

Forbidden approaches:

  • any usage of Intl.*
  • any usage of toLocale*

If a rule affects system correctness or persistence, it does not belong in a Display.


Ownership & Placement

  • Displays belong to the presentation layer
  • They are frontend-only
  • They are not shared with the backend or core

Placement rule (strict):

  • Displays live under apps/website/lib/display-objects/*.
  • Filenames MUST match the class name with .tsx extension (e.g., RatingDisplay.tsx contains class RatingDisplay)

Relationship to View Models

  • View Models MAY use Displays
  • Displays MUST NOT depend on View Models
  • Displays represent parts
  • View Models represent screens

Additional strict rules:

  • View Models SHOULD compose Displays.
  • 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.

Testing

Displays SHOULD be tested because they often contain:

  • locale-specific behavior
  • formatting rules
  • edge cases visible to users

Additionally:

  • test determinism by running the same inputs under Node and browser contexts (where applicable)
  • test boundary rules (no Intl.*, no toLocale*)

Summary

  • Displays encapsulate how something looks
  • View Models encapsulate what a screen needs
  • Both are presentation concerns
  • Neither contains business truth

In one sentence: Displays are Value Objects for UI display, not utility functions.