Context. surface studio · domain generation · route /studio/generation/nyx-3d · auth signed-in + creator (proxy-gated; not anonymous, not search-indexed) · source apps/oshun/web/src/app/studio/generation/nyx-3d/page.tsx
Last walked. 2026-06-03 automated runtime probe (Playwright headless) — prod build + mock BFF; render, HTTP 200, server-rendered <h1>, 0 page errors verified. Evidence: WALKTHROUGH/results/walkthrough-runtime-probe-2026-06-03.md
Purpose#
The approved Nyx 3D sky-event briefing surface (§24.6 / §24.8). Renders the
Nyx3DBriefingCard against upcoming, ephemeris-derived sky events
(GET /v1/isis/nyx-3d/events) and submits through
POST /v1/isis/nyx-3d/generate. The 3D pipeline class is server-authoritative —
the client only sends the chosen eventId; the backend runs the real sky-event
validation + entitlement, then enqueues (Meshy is the registered provider when
OSHUN_MESHY_API_KEY is set), fail-closed 503 otherwise.
Entry points#
- Direct URL / bookmark —
/studio/generation/nyx-3d(proxy-gated to authed creators;robots: noindex/nofollow/noarchive/nosnippet) - Studio shell nav —
active="studio"(shortcut6), generation sub-area - Sibling generation surfaces — curated-cards / music / living-scene
- Nyx domain bridge — conceptually downstream of the customer Nyx sky
surfaces (
/nyx/tonight,/nyx/sky-almanac); the events here are the same ephemeris events surfaced for briefing
Layout regions#
- Header: shell header (
ShellLayout active="studio") - Main:
<section data-nyx-3d-studio><h1>Nyx 3D Briefing</h1>— page heading, rendered in all four states (error → insidedata-nyx-3d-error; loading → insidedata-nyx-3d-loading; empty → insidedata-nyx-3d-empty; populated → top of the studio section), plus a lede<p>"Generate a 3D briefing for an upcoming sky event. The pipeline class is server-authoritative; outputs are provenance-tracked."- Consent panel (
.panel,data-nyx-3d-consent) — single terms checkbox Nyx3DBriefingCard(viaCardShell) — sky-event picker + pipeline-class readout + preflight meta + Generate- Status line (
.panel,data-nyx-3d-status) after a submit attempt
States#
- Loading —
data-nyx-3d-loadingpanel "Loading upcoming sky events…" while the GET is in flight, or when the response lackscard/provenance - Empty —
data-nyx-3d-emptypanel "No upcoming sky events are available for a 3D briefing right now." whenevents.length === 0(honest empty — no fabricated events) - Populated — consent panel +
Nyx3DBriefingCardwith the event select defaulted to the first upcoming event - Entitlement-denied / feature-unavailable — handled by
CardShell - Submit accepted — "Accepted — queued for 3D briefing generation."
- Submit rejected (503) — "The 3D sky-briefing provider is not configured for this deployment yet."
- Submit rejected (403) — "Not available:
" - Submit rejected (404) — "That sky event is no longer upcoming."
- Submit rejected (422) — "This briefing is outside the approved envelope."
- Error (load failed) —
data-nyx-3d-error"The Nyx 3D briefing surface is unavailable right now:" - Offline — load GET fails → error panel; submit POST → "Submission failed."
- Gated — proxy (creator) + entitlement (server)
- Standalone PWA — renders within shell
Interactions#
- Terms consent (checkbox,
data-nyx-3d-consent-checkbox)- Function: toggles
consentAccepted; setsconsentIdtoconsent-nyx3d-<userId>when accepted - Screen reader: announces "I accept the curated-generation terms for this 3D sky briefing."
- Function: toggles
- Sky event (select,
data-field="eventId")- Function: chooses the
SkyEventBriefing; options areavailableEvents[].eventLabel; selecting one shows its approved pipeline class (<code>{approvedPipelineClassId}</code>) inputsValidis true only when a listed event is selected
- Function: chooses the
- Direction (textarea) — regenerate steer
- Generate (button,
data-card-action="generate")- Function:
submit({ eventId, pipelineClassId }); onlyeventIdis sent on the wire (POST /v1/isis/nyx-3d/generatebody{ eventId }) — the pipeline class is resolved server-side - Disabled when: no event selected / preflight blocked / no consent / busy
- Function:
- Regenerate with direction, Variant compare, Send to editorial,
Takedown — shared
CardShellcontrols (last two() => undefined)
Data & contracts#
- Reads:
GET /v1/isis/nyx-3d/events→{ events: SkyEventBriefing[], creatorTier, card: CardSpec | null, provenance: ProvenancePreview | null }whereSkyEventBriefing = { eventId, eventLabel, approvedPipelineClassId } - Writes:
POST /v1/isis/nyx-3d/generate—{ eventId }only; pipeline-class server-authoritative; fail-closed 503 until provider configured - Realtime: None.
- Caching: client fetch on mount
- Auth/role check: proxy (creator) + entitlement (server) + sky-event validity (server, "no longer upcoming" → 404)
- Contracts:
@oshun-web/isis-curated-cards(CardSpec,ConsentConfirmation,ProvenancePreview,PENDING_COST_COEFFICIENTS);SkyEventBriefingdefined inline + inNyx3DBriefingCard.tsx
Cross-references#
- Parent:
../studio-overview.md - Siblings:
studio-generation-curated-cards.md,studio-generation-music.md,studio-generation-living-scene.md - Customer Nyx surfaces:
../../customer/06-nyx/nyx-tonight.md,../../customer/06-nyx/nyx-sky-almanac.md - Component sources:
apps/oshun/web/src/components/studio/generation/Nyx3DStudio.tsx,Nyx3DBriefingCard.tsx,CardShell.tsx
Open questions / known gaps#
-
tenantIdis''anduserIddefaults to'me'inNyx3DStudio— confirm session/proxy resolution. - Confirm the
eventIdset here is sourced from the same ephemeris that feeds/v1/nyx/tonightand/v1/nyx/sky-almanac, so a customer-visible event and its 3D briefing always agree.