Galaxy Map
A live network graph of every sector and page in the console, built from the nav config and rendered client-side.
The Galaxy Map is a single-page network graph of the whole console. It is not a geographic map — it's a map of the dashboard itself: the brand core sits at the centre, each sidebar group is a sector star, each page orbits its sector, and dashed wormhole edges show how data flows between pages across sectors. It's the "I know what I want but not where it lives" view — click any star to jump to it.
It is intentionally read-only and client-rendered. The page fetches the
navigation taxonomy from /api/nav (which serves src/lib/nav-config.yaml) and draws
it with reagraph over a deterministic CSS starfield. Add a page to the nav config and
it appears on the map automatically — there is no separate registry to maintain.
What it renders
| Element | Source | What you see |
|---|---|---|
| Core | nav-config.yaml brand | The R2-D2 root star — the gravitational anchor; click → Overview |
| Sectors | each nav group | One large star per group (Node Red, Restreaming, Imp Intel, The Force, …), coloured by SECTOR_COLOR |
| Pages | each group's items | Smaller stars orbiting their sector; click → deep-link into that page |
| Wormholes | the wormholes array | Dashed, labelled edges showing data flow between pages (e.g. feeds → Holocron) |
| Detail panel | GALAXY_COPY + nav description | Slide-over with a thumbnail, an "About" blurb, and a clickable "Connections" list |
Layout is switchable in the top-right toolbar — 3D (default orbit), Force 2D, Radial, and Hierarchical — and the legend lists every sector by colour.
Sectors and the data-flow story
The wormhole edges are the interesting part: they encode how the planes actually talk to each other, not just the menu tree. A few of them:
- Restreaming feeds → Holocron (camera markers on the map)
- Temple Archives Feed Sync → HoloNet (REST republished onto MQTT)
- Imp Intel → Medusa → COP — the calibration-to-fusion path (below)
Imp Intel is passive calibration, and Medusa is planned. The map shows the Imp Intel sector (Imperial Intelligence) as the UXV testing, calibration, and evaluation workspace used during TaskForce-X sessions — R2-D2 holds no authorization to task nations or live sensors. Its calibrated readings, plus the MQTT backbone, feed Medusa (Hydroid) — a contact-fusion engine that publishes unified contacts to the COP. Medusa does not exist as a page yet, so it has no nav entry; the map surfaces it as a synthetic "Medusa (planned)" node with no "Open" action, purely so the calibration → fusion → COP flow is visible.
How nodes get their copy
Each star's "About" text comes from GALAXY_COPY in src/components/GalaxyMap.tsx —
richer, GUI-friendly descriptions written for someone learning the console. If a node
isn't listed there, the map falls back to a sanitized version of the page's
nav-config.yaml description (sanitizeCopy strips internal tracker refs like bd-…
and RS-7 so they never reach the UI).
Thumbnails come from /media/thumbnails/<slug>.jpg, captured by npm run thumbnails
(a Playwright pass). A node with no captured image — or the planned Medusa node, which
has no page — shows a sector-coloured placeholder instead.
The detail panel
Clicking a star opens a slide-over (DetailSlidePanel, the shared primitive). It shows,
in order:
- A thumbnail (or placeholder).
- A context CTA — "Open page →" for a page, "Zoom to this Sector →" for a sector,
"Open Overview →" for the core. Planned nodes (no
href) get no Open CTA. - About — the description resolved as above.
- Connections — every node on the other end of an edge, with the relation label. Clicking one drills into it and pushes a Back breadcrumb, so you can walk the graph without losing your place.
There is no editing here; mutations live on the plane the resource belongs to.
Adding to the map
Because the graph is derived from the nav config, most changes are free:
- New page or group → add it to
nav-config.yaml; it appears next render. - Custom blurb → add a
GALAXY_COPY['<sector>:<id>'](or'sector:<group>') entry. - New sector colour → add the group to
SECTOR_COLOR(and aPALETTEtoken); otherwise it falls back to the core teal and won't get a legend swatch. - New data-flow edge → add a
[source, target, label]tuple to thewormholesarray. Both node ids must exist or the edge is silently skipped. Page ids are'<group>:<item.id>'(e.g.'Imp Intel:isr').
Why it's a single file (and stays that way)
The renderer is one large component (src/components/GalaxyMap.tsx). It's the kind of
component people instinctively want to break up — resist. Every piece of state (layout,
camera, hover, selection, drill history) is co-tenanted in one render pass, and the
camera-tuning effects all reach into the same reagraph controls. Factoring it out
trades a little tidiness for a lot of cross-component coordination.
Built on
| Layer | Tech | Page |
|---|---|---|
| Rendering surface | reagraph (WebGL force/radial/hierarchical layouts) | reagraph |
| Graph source | /api/nav → src/lib/nav-config.yaml | Next.js + React |
| Detail slide-over | DetailSlidePanel shared primitive | (no library) |
| Thumbnails | /media/thumbnails/<slug>.jpg via npm run thumbnails (Playwright) | (build step) |
| Starfield backdrop | deterministic CSS box-shadow field (mulberry32 seed) | (no library) |