Frontend Convention — UI naming, composition, and visual vocabulary
From the Meridians Wiki · Public · Maintained · joint
How code names are formed in this codebase (companion to LANGUAGE.md, which defines the domain vocabulary). This is the present convention — match it when adding or renaming code.
The formula: Domain + Role
Every component / surface name = a domain term (from LANGUAGE.md) + a role word for its physical place/shape. Reads as "what it's about" + "where it is". e.g. ScenePanel, StageBar, ForceTimeline, DecisionView.
Role lexicon (precise)
| Role | Means | Notes |
|---|---|---|
| Shell | a top-level page frame that hosts a whole surface | one per surface: WorkspaceShell (domain workspace), GatewayShell (instance home + auth — a misnomer, see Platform naming), ScenarioShell (live game table), PortalShell (the meridians.global site). MobileWorkspace is the phone variant of WorkspaceShell. |
| Rail | thin vertical strip of items/icons | left story rail; inspector icon rail |
| Bar | thin horizontal strip of controls | top of a region (StageBar, RunBar, FuturesBar) |
| Panel | a large rectangular region of content | resizable / dockable; the inspector/sidebar bodies. When a concept has both (e.g. Readings): View = the stage surface, Panel = the inspector mirror of the same thing. |
| View | a full center surface the Stage swaps between | keep the …View suffix; BoardView, ReadingsView, NetworkView, DecisionView, … |
| Stage | the center surface that hosts one View at a time | switched by StageBar → state.stageView |
| Timeline | a horizontal time-ordered band | scenes, forces |
| Modal | overlay dialog | BranchModal, ScenarioModal, ApiKeyModal |
| Popover | small anchored overlay | |
| Chart | one visualization | |
| Dashboard | a full analytics surface | |
| Detail | inspector body for one entity | panel content (CharacterDetail, SceneDetail, …) |
| Slide | one deck slide | |
| Palette | floating action menu | StagePalette |
Domain lexicon (draw names from LANGUAGE.md, not synonyms)
Domain · Scene · Arc · Branch · Thread · Belief · Stance · Stream · Merge · Priors · Capture · Scenario · Explore · Readings · Variables · Phase Reasoning Graph / Phase Graph (PRG) · Causal Reasoning Graph / Causal Graph (CRG) · Decision · Mind (the stance/machinery cluster) · Signals (the Capture cluster) · Force (Fate/World/System) · Network · World · System · Board · Substrate · Perspective · Member · Agent · Invitation.
Retired aliases — do not use as code names: Driver (→ Capture / Prior), Queue (→ Priors), Series (→ Domain), Mode (→ Phase, for the PRG), Control (→ Mind), canvas (→ Stage), Playback (→ Scenario), Conviction (the game → Scenario; ConvictionShell→ScenarioShell, useConviction→useScenario, etc.). Exception: the in-game currency you pay to commit stays conviction (Seat.conviction, ConvictionEconomy, CONVICTION_*, evidenceFromConviction) — you still "pay conviction" inside the Scenario game.
The load-bearing four are *Shell · *View · *Panel · *Detail — get those right and the rest
follow. This file owns the convention; agent briefs and skills should link here rather than restate it.
Platform & gateway naming (shipped — see GATEWAY.md 🔒)
The platform layer adds terms that collide with shipped ones if we're not deliberate. These decisions are settled and in code:
- The
GatewayShelltrap → the meridians.global site isPortalShell, NOTGatewayShell. TheGatewayShellis the instance home console (spine + stage: Games / Domains / Extraction / Invitations) — a slight misnomer, but it's shipped and stays. The hosted gateway atmeridians.global(landing · account · Admin console) is a different frame →PortalShell(src/features/gateway/landing/PortalShell.tsx; cosmos + glass). Never call the meridians.global site "GatewayShell". - "Director" spans two layers — keep the word, know the layer. Platform Director = the Supabase
account owner (owns products, pays). In-instance
director= the top role in the shipped 5-tier access ladder (Guest→Viewer→Contributor→Manager→Director). They coincide (the owner is their instance's director) but are separate systems: platform Director lives indirectors(Supabase); in-instance director lives ininstanceMembers(the master's registry). Say "platform account" vs "in-instance member / people" when the layer matters. - "Admin" (platform) vs "Manager" (in-instance role) — no crossing. Admin = the platform operator
(
platform_admins/ the gateway/admin; us). Manager = the ladder role just below director (the director's deputy inside one instance), renamed from "admin" so the word is free for the platform. There is no in-instance "admin" and no platform "manager". TheMemberRoleliteral is'manager'(src/types/domain/access.ts); the platform table isplatform_admins. - Products:
LicenseandHosted(settled). License = the BYOK Electron app (cheap flat). Hosted = the managed Fly VM (pricier). Avoid "Managed" (ambiguous) and "tier"/"seat" (there are no tiers — one License plan; the tunnel is a BYOK ngrok key). A director's products are per-subscription (hasLicense/hasHosted), not a field — both can be true. - "Instance" = one running host. The Electron app (License) or a Fly VM (Hosted). Its DB row is
instances(Hosted only). Don't call it a "tenant" (control-plane word we don't use) or a "server". - "Domain" is triple-overloaded — disambiguate every time. (1) domain = the product knowledge
structure (LANGUAGE.md — the thing users build). (2) domain name = the DNS host an instance runs on
(
<slug>.meridians.global/ a custom domain). (3)directors/account domain = platform data. In gateway code + copy, say "domain name" or "hosting domain" for DNS, never bare "domain". - Entitlement predicates:
hasLicense(director)/hasHosted(director)— read thesubscriptionsrows; never adirectors.productcolumn (it doesn't exist). - Suffixes carry over: the gateway's frames are
PortalShell+*View/*Panel/*Modalas usual (e.g.FleetConsoleis a Dashboard;SubdomainClaim/CustomDomainSetupare onboarding panels;LicenseStatusChipa chip). Same lexicon, new surface.
What's consistent (leave alone)
-
Casing: PascalCase components, kebab-case lib, domain-foldered prompts.
-
File families:
…-graph.ts(world/system/network/phase-graph);…-export.ts; thefutures-engine/-state/-remaptrio; thegame-theory*family;*Slide/*Modal/*Chart/*Detailsuffixes. -
stageViewliterals track their UI labels. The union insrc/types/domain/view-state.tsis the source of truth, and most members now read as the user sees them ('opinion','notes','streams','cycles','projections','runs','operations') so code and screen use one word. Two kinds of exception, both deliberate:- Legacy literals kept for persisted state —
'mode'is labelled Phase / Phase Graph in the interface, and'present'labels as Present. Renaming them would strip storedviewState, so they stay; only the label moved. - Retired deep-link values are mapped at the boundary, never re-persisted —
useDomainDeepLinkstranslates old URLs (?view=sources→cycles,schedule→operations,loop/stories→inbox) so old links keep working without the retired literal re-entering state.
Adding a mode: name the literal after its label, and if you rename an existing one, add the old value to the deep-link mapping rather than leaving a dead URL.
- Legacy literals kept for persisted state —
-
Pentad archetypes are 32 Domain work forms over exact formed/latent force profiles. Use the canonical names from
pentad-archetype.ts; do not concatenate force labels or reuse Scene Sign names. The same five-bit coordinate has two altitudes: a Sign names Scene movement, an archetype names whole-work composition. A counterform reverses all five bits and is a semantic contrast, never a quality verdict.