Feature Map
Canonical index of every screen, panel, overlay & sub-view · feature_map() in the dev console
feature-map.md; the styling source of truth is style-guide.md + /style-guide/.
00 · Overview
Top-level routing happens in src/App.tsx and is driven by state.screen
(one of 'title' | 'map' | 'docked' | 'denied' | 'transit' | 'gameover', defined in src/state/types.ts).
Persistent chrome stacks on every non-title screen; overlays and modals stack on top.
Quick reference
| Resource | Path |
|---|---|
| Top-level routing | src/App.tsx |
| Game state shape | src/state/types.ts |
| Reducer | src/state/reducer.ts |
| Static game data | src/data/ |
| Pure game logic | src/engine/ |
| Component CSS | co-located: src/components/Foo.tsx + Foo.css |
| Style spec | style-guide.md, style-guide/index.html (/style-guide/) |
01 · Window Taxonomy
Every visible UI surface, grouped by its window class. One row per pane — tabs inside a tabbed window are listed individually, not folded into the parent.
| Class | Definition |
|---|---|
| Screen | Full-canvas window. Mutually exclusive with other screens. Driven by state.screen. |
| Pane | One tab inside a tabbed screen. |
| Sub-surface | Internal region of a screen with its own chrome (rails, strips, rosters). |
| Overlay | Floats above the active screen, persists across screens, dismissed by the user. |
| Modal | Floats above, blocks input, decision-driven dismissal. |
| Persistent chrome | Always rendered, not a window. |
1a · Screens
| Pane | File | state.screen | Game systems housed |
|---|---|---|---|
TitleScreen | src/components/TitleScreen.tsx | title | Main menu — new game, load, options. Bypasses TopBar / overlays. |
StarMap (map mode) | src/components/StarMap.tsx | map | Travel / pathfinding, scan / survey, plot routing. Sub-surfaces in §1c. |
StarMap (transit mode) | src/components/StarMap.tsx | transit | Same SVG canvas as map, but the TransitConsole bottom strip replaces FlightPlanStrip. Ship sprite animates the edge. |
DockPanel | src/components/DockPanel.tsx | docked | Two-column docked view — wraps StationPanel (left) + ShipPanel (right). Tabs in §1b. |
DeniedPanel | src/components/DeniedPanel.tsx | denied | Hostile / story-locked station rejection. Faction system surfaces error here. |
GameOverPanel | src/components/GameOverPanel.tsx | gameover | End-of-run summary. |
src/components/TransitScreen.tsx exists but live transit is rendered by StarMap in transit mode. Don't add to it.
1b · Panes (tabs)
StationPanel — left column of DockPanel
File: src/components/StationPanel.tsx. Each tab's visibility depends on station.shipyard, station.outfitting, etc.
| Pane | Tab key | Game systems housed |
|---|---|---|
StationPanel.info | info | Station details, description, environment (atmosphere / temp / gravity), faction info, gatherables. |
StationPanel.comms | comms | Mission board — accept / hand-in story steps. Faction rep gating. |
StationPanel.market | market | Buy / sell goods. Row click opens GoodInfoModal. |
StationPanel.outfitting | outfitting | Install / uninstall modules; warehouse parking. |
StationPanel.shipyard | shipyard | Browse and buy ships. |
StationPanel.crew | crew | Hire / dismiss crew. |
ShipPanel — right column of DockPanel
File: src/components/ShipPanel.tsx.
| Pane | Tab key | Game systems housed |
|---|---|---|
ShipPanel.ship | ship | Stats only. Cargo / fuel / crew / engine / scanner / hull readouts, mass & speed, crew roster. Inline subtext mentions module names but does not render the schematic. |
ShipPanel.schematic | schematic | Modules only. Renders ShipSchematic — slot grid, drag-drop install, warehouse. Single home for module visualisation + installation. |
ShipPanel.cargo | cargo | Inventory list with quantities + value. |
ShipSchematic to the ship tab. Modules belong on schematic; the ship tab is a stat readout. Both used to render the schematic — the duplication was confusing.
StoryPanel — global overlay (L key)
File: src/components/StoryPanel.tsx.
| Pane | Tab key | Game systems housed |
|---|---|---|
StoryPanel.missions | missions | Active steps, ready-to-hand-in, chain progress, story-flag unlocks. |
StoryPanel.codex | codex | Public FIELD RECORDS (visit-unlocked lore dossiers) + story-gated CLASSIFIED intel (secrets, sealed until their reveal flag fires). |
ShipPanel; that duplication was removed. Don't add them back.
1c · Sub-surfaces (Star Map zones)
StarMap.tsx is a multi-zone shell, not a single pane. Each surface is a defined chrome region with its own role.
| Pane | Sub-component | Class root | Game systems housed |
|---|---|---|---|
StarMap.FilterChips | FilterChips | .starmap-corner-hud, .starmap-filters | Interactive faction-filter chips (All / per-faction / Neutral / Hostile). Dims non-matching nodes. |
StarMap.ZoomControls | inline | .starmap-zoom | Zoom in/out, percentage, reset (RST), roster toggle (≡). |
StarMap.IntelPanel | IntelPanel | .starmap-intel | Selected-station survey readout (scan-gated rows, survey-progress bar, SCAN / CENTER / DOCK). Persists until Esc or close. |
StarMap.SectorRoster | SectorRoster | .starmap-roster | Collapsible searchable list of known stations, sorted by distance. Click selects + plots + focuses. |
StarMap.IdleHint | IdleHint | .starmap-idle-hint | Tiny hint pill when nothing is plotted. |
StarMap.FlightPlanStrip | FlightPlanStrip | .starmap-flight | Waypoint trail, 5-stat totals, next-leg row, JUMP button. Survives Intel close — Esc again clears. |
StarMap.TransitConsole | TransitConsole | .starmap-transit-console | Origin → destination, long progress bar with ship marker, ETA / elapsed, risk pips, event-window state, drive status. |
StarMap.StationNode (×N) | StationNode | .starmap-node | Per-station glyph: ring (category vs. faction), pulse on current, dashed ring on plotted, hostile / dimmed / unknown variants. |
IdleHint / FlightPlanStrip / TransitConsole renders at a time.
1d · Overlays
| Pane | Component | Trigger | Game systems housed |
|---|---|---|---|
| Story / Missions | StoryPanel | L key or [L] MISSIONS button | Story progression, codex. See §1b for tabs. |
| Controls / help | ControlsOverlay | ? or / key | Keyboard + mouse reference. |
App.tsx).
1e · Modals
| Pane | Component | Trigger | Game systems housed |
|---|---|---|---|
| Event | EventModal | Reducer sets state.activeEvent | Random encounters. Blocks input; 1 / 2 / 3 to pick a response. |
| Arrival | ArrivalModal | After transit → map with currentStationId set | Arrival flow — DOCK / MINE / EXPLORE / STAY IN ORBIT. Faction-rep gating. |
| Good info | GoodInfoModal | Click a market row in StationPanel.market | Good details + lore tip. |
| Scan toast | inline .starmap-message in StarMap | Reducer sets state.message after SCAN_STATION etc. | Brief confirmation. Top-centre, auto-dismisses. |
1f · Persistent Chrome
Rendered on top of every non-title screen. Not windows — never call them "panels".
| Element | Component | File | Game systems housed |
|---|---|---|---|
| Top bar | TopBar | src/components/TopBar.tsx | Day · credits · fuel (segmented bar) · hull (segmented bar) · location · [M] DOCK (map only) · SAVE · MENU. |
| Missions toggle | inline .story-global-btn | src/App.tsx | [L] MISSIONS — opens the Story overlay. |
| Notification toast | NotificationToast | src/components/NotificationToast.tsx | Game-event toasts surfaced from the reducer. |
| Error boundary | ErrorBoundary | src/components/ErrorBoundary.tsx | Wraps the shell — renders a fallback on thrown error. |
| Scanlines + small-viewport warning | inline | src/App.tsx | Pure visual overlay; no logic. |
1g · Proposed — new homes for orphaned systems
These game systems exist in the engine / data but have no canonical window today — they're either scattered inline across unrelated panels or invisible after the moment they fire. Each row below is a proposed new pane; none of these are implemented yet. Documenting them as the agreed home prevents the next ad-hoc inline render from deepening the scatter.
| Proposed pane | Status | What it would show | Source |
|---|---|---|---|
StoryPanel.factions |
proposed | All four factions at a glance, each with current rep, rank, trading modifiers, key stations, story chains gated by them. | data/factions.ts, state.factionRep; reuse getRepRank / getRepModifiers / getRepProgress from data/factions.ts. |
StoryPanel.log |
proposed | Reverse-chronological event history — events fired, choices taken, outcomes. Currently events vanish after RESOLVE_EVENT. |
Needs reducer to keep a bounded state.eventHistory array on each RESOLVE_EVENT. |
StoryPanel.gathering (optional, lower priority) |
proposed | Resources gathered, cooldowns, eligible nodes. | state.gatheringHistory (new) + station.gatherables lookups. |
StoryPanel.factions is the highest-value addition (rep already exists; players can't see all standings at once). StoryPanel.log is medium. StoryPanel.gathering is optional.
02 · Shared Components
Canonical implementations of UI patterns that appear in multiple panes.
Located at src/components/shared/. Do not duplicate these inline —
import from shared/. If you find a pattern rendered in 2+ panes with cosmetic drift,
promote it here.
| Component | Class prefix | Consumers | Renders |
|---|---|---|---|
ObjectiveList | .obj-* | StoryPanel · StationPanel.comms · ShipPanel | Mission objective checklist with progress + done states. |
CodexList | .codex-* | StoryPanel.codex | Public FIELD RECORDS — discovered lore dossiers + undiscovered titles list. |
ClassifiedList | .classified-* | StoryPanel.codex | Story-gated CLASSIFIED intel — revealed secret bodies + sealed teaser rows. Gated by secrets.ts reveal flags; in-game only, never on public pages. |
MissionStepCard | .mission-step-* | StoryPanel.missions | Mission step card — chain badge, title, description, objectives, reward. Variants: default / ready-handin / auto-complete / new-mission. |
ChainRow | .mission-chain-* | StoryPanel.missions | Chain progress row with status pill (LOCKED / IN PROGRESS / COMPLETE), faction, step count, optional prereq. |
StoryFlagRow | .mission-flag-* | StoryPanel.missions | Single unlock row in the UNLOCKS section. |
StatBar | .stat-bar-* | TopBar (fuel + hull) · ShipPanel (cargo / fuel / crew / speed / scanner / hull) | Segmented stat indicator. Supports fixed colour, tier mode (auto low/mid/ok colour by pct), and blinkOnCritical (≤ 10%). Replaces the previous FuelBar / HullBar / Bar. |
shared/Foo.tsx + Foo.css with a single foo-* class prefix, replace the duplicates, and add a row to this table.
03 · Engine Modules
Pure modules under src/engine/. No React imports. Each pane consumes zero or more of these to compute display values.
| Module | Owns | Consumers |
|---|---|---|
travel.ts | Path-finding, distance, fuel cost, station lookup | StarMap, FlightPlan, Transit |
economy.ts | Pricing, stock, supply/demand modifiers | StationPanel (market) |
shipStats.ts | Engine speed, fuel efficiency, cargo capacity, scanner depth, cargo risk | TopBar, StarMap, ShipPanel |
events.ts | Event rolls + risk evaluation | StarMap (transit), EventModal |
environment.ts | Thermal / radiation hazards | reducer.applyArrivalProcessing |
story.ts | Story step graph, station accessibility | StarMap, StationPanel.comms, StoryPanel |
objectives.ts | Derives per-step objective lists | shared/ObjectiveList |
hexGrid.ts | Hex maths legacy | — |
04 · Static Data
All under src/data/. Loaded at build time. Every entity follows
the same convention: one JSON file per entity, aggregated
into an array by a thin .ts wrapper using
import.meta.glob. No data is inline in TypeScript.
| Wrapper | JSON glob | Drives |
|---|---|---|
stations.ts | stations/*.json | Every node on the star map; market exports/imports; gatherables. |
ships.ts | ships/*/info.json | Shipyard inventory + archetypes + gameplay stats. |
modules.ts | modules/*.json | Outfitting catalogue (engines, fuel tanks, scanners, etc.). |
goods.ts | goods/*.json | Tradeable items + categories. |
factions.ts | factions/*.json | Faction list, colour, reputation thresholds. Also exports rep-tier logic. |
crew.ts | crew/*.json | Hireable crew templates. |
story.ts | story/*.json | Mission chains, objectives, dialogue. |
lore.ts | lore/*.json | Public codex dossiers (FIELD RECORDS) unlocked by visits / events. Exports both LORE_ENTRIES (array) and LORE_BY_ID (Record). |
secrets.ts | secrets/*.json | Story-gated CLASSIFIED codex entries. Each has a revealFlag; isSecretRevealed() checks it against storyFlags. Bodies lifted from STARWIND_LORE.md §10. |
stationInventory.ts | — | Pure filter logic. Resolves station services against storyFlags + factionRep. |
*.json. If you find inline data in a .ts file under src/data/, split it into per-entity JSON files and reduce the .ts to an import.meta.glob wrapper. The existing wrappers are the template.
05 · Keyboard Map
Handled in App.tsx (handleKey) unless noted. ? / / always toggles ControlsOverlay.
| Key | Screen(s) | Action |
|---|---|---|
| M | map | Dock at current station |
| M | docked | Undock back to map |
| K · S · U | map | Alias for dock |
| J | map | Jump to plotted destination (handled in StarMap.tsx) |
| R | docked | Refuel |
| L | anywhere | Toggle Story / Missions overlay |
| 1 · 2 · 3 | EventModal | Pick response option |
| Esc | EventModal | Decline (encounters & opportunities only) |
| Esc | map | Close Intel → clear route → close overlay (cascading) |
| ? · / | anywhere | Toggle ControlsOverlay |
| ` | non-title | DEBUG_CHEAT action dev |
The canonical list rendered to the player lives in src/components/ControlsOverlay.tsx. Keep this table and that array in sync.
06 · Screen Transitions
┌──────────┐
│ title │
└────┬─────┘
│ start / load
▼
┌──────────┐ ┌─────────────┐
undock ◀────┤ map ├─── jump ─────▶ │ transit │
│ │ │ │
│ ▲ │ complete │ (StarMap │
│ └──────┼────────────────┤ in │
│ │ │ transit │
│ dock │ │ mode) │
└────┬─────┘ └─────────────┘
│
▼
┌──────────┐
│ docked │
└────┬─────┘
│
hostile / locked
▼
┌──────────┐
│ denied │
└──────────┘
hull == 0 / catastrophic event from any state ▶ gameover
07 · When to Update This File
You must update this file (and its markdown twin feature-map.md) when you:
- Add a new top-level screen (new value of
state.screen). - Add a new tab to
StationPanel,ShipPanel, orStoryPanel. - Add a new persistent chrome element rendered above every screen.
- Add a new overlay or modal.
- Add a new sub-surface to
StarMap. - Add a new engine module under
src/engine/. - Add a new key binding handled by
App.tsxor a screen-level component. - Implement one of the §1g proposed homes — move its row from §1g into §1b in the same change.
You do not need to update this file for:
- Internal refactors that don't change the surface area.
- Visual-only tweaks (those go in
style-guide.md). - Data-only additions (new stations, ships, goods, missions) — those flow through existing tables.