V1 Web PWA · Surface walkthrough

/domains/[domainId] — Canonical domain experience

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections3 minread

On this page

Context. surface customer · domain shell-routing · route /domains/[domainId] · auth signed-in · source apps/oshun/web/src/app/domains/[domainId]/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md

Purpose#

Long-form domain route. Picks per-domain SEO metadata from a static DOMAIN_META table and renders the shared DomainRouteExperience client composition with a sanitised single-value searchParams shape. Unlike /d/[domain]/[[...path]] (which only redirects), this route mounts the actual UI for the domain.

Entry points#

  • Quick-actions and shell nav that prefer the canonical /domains/<id> form
  • Domain card on / (DomainCardGrid → canonical route)
  • Cross-domain bridge links
  • Recommendation cards
  • Direct URL / bookmark — yes (auth required)
  • ?origin, ?stack, ?path, ?ref, ?offline, ?reason, ?unavailable query params (all forwarded to DomainRouteExperience)

Layout regions#

page.tsx is a server component. Validates params.domainId against isWebNavigableDomainId (calls notFound() if invalid). Otherwise renders <DomainRouteExperience domainId={domainId} searchParams={...}> with a single-value-flattened search-param shape (toSingle() collapses arrays to their first entry).

  • DomainRouteExperience: the actual domain composition. Layout regions live in apps/oshun/web/src/components/DomainRouteExperience.tsx. Walker should confirm region names by reading that file; from the page contract:
    • Honours origin, stack, path, ref for navigation context
    • Honours offline, reason, unavailable for fallback / framing states

States#

  • Unknown domainId — fails isWebNavigableDomainIdnotFound()
  • Known domain (default)<DomainRouteExperience> renders the domain's canonical experience
  • ?origin=home — domain mounted with home-origin context
  • ?stack=<name> — verify what stack controls
  • ?path=<sub> — domain mounts at a deep sub-path
  • ?ref=<source> — referrer attribution
  • ?offline=1 — domain mounts in offline framing
  • ?reason=<code> — reason for unavailable / framing surface
  • ?unavailable=1 — unavailable framing surface
  • Anonymous user — middleware redirects to /welcome
  • Standalone PWA — verify shell renders cleanly

Interactions#

Interactions live inside DomainRouteExperience and are domain-specific. The page itself contributes:

  • No DOM-level interactions; pure wiring of params → component.

Per-domain SEO metadata#

generateMetadata picks copy from DOMAIN_META:

  • tara: "Tara — Meditation & Breathwork" / OG "Tara | OSHUN — Meditation & Mindfulness"
  • veritas: "Veritas — Truth & Information" / OG "Veritas | OSHUN — Truth-Seeking & Knowledge"
  • nyx: "Nyx — Night Sky & Astronomy" / OG "Nyx | OSHUN — Night Sky Exploration"
  • arete: "Arete — Growth & Habits" / OG "Arete | OSHUN — Personal Growth & Excellence"
  • nisaba: "Nisaba — Primary Texts & Scholarship" / OG "Nisaba | OSHUN — Texts, Commentary & Research"
  • metis: "Metis — Learning & Tutoring" / OG "Metis | OSHUN — Learning, Tutoring & Mastery"

Each carries:

  • alternates.canonical: '/domains/<id>'
  • OG image: /og/domain-<id>.png
  • Twitter summary_large_image card

Unknown domains return { title: 'Domain' } (and notFound() from the page body).

Data & contracts#

  • Reads:
    • params.domainId: string
    • searchParams: Record<string, string | string[] | undefined>
  • Writes: none from this page
  • Realtime: none
  • Caching: not explicitly cached at this level; DomainRouteExperience manages its own
  • Auth/role check: not in PUBLIC_PREFIXES; signed-in only
  • Metadata: generateMetadata resolves per-domain title / description / OG / Twitter

Cross-references#

  • Sibling shell-routing helper: d-domain-path.md
  • Canonical domain walkthroughs:
    • ../03-tara/tara.md
    • ../04-arete/, ../05-veritas/, ../06-nyx/, ../07-nisaba/, ../08-metis/
  • Component sources:
    • apps/oshun/web/src/components/DomainRouteExperience.tsx
    • apps/oshun/web/src/navigation/routes.ts (isWebNavigableDomainId)

Open questions / known gaps#

  • Read DomainRouteExperience.tsx to enumerate the actual layout regions and per-domain branching behaviour
  • Document the full set of path, origin, stack, ref values DomainRouteExperience recognises
  • Confirm OG image routes (/og/domain-<id>.png) exist for all six domains
  • Confirm whether /domains/[domainId] is the canonical route per domain or whether per-domain routes (/tara, /veritas, etc.) are preferred — affects coverage in matrix/routes.csv
  • No telemetry tagged from this routing layer; verify DomainRouteExperience emits domain-entry events