← all components

Constellation

The most technically ambitious surface: a live d3-force simulation over every entity and typed edge in the Well, rendered on canvas with three encodings that carry real meaning — depth is age, brightness is recency, size is salience. Everything around the canvas exists to let you steer it.

What is faithful here. The chrome on this page — lens bar, legend, dossier, graph controls — is the shipped markup under the shipped CSS. The field itself is a static paint: a seeded, settled frame that reproduces the engine's three encodings and its edge styling, but does not run d3-force, drag, zoom or hit-testing. See the note on the issues page.
00

The field

A canvas that fills the remaining height of the view, on a radial gradient running from surface light at the top to --field-bottom at the floor. Age pulls a node down that column; the engine exposes the strength of that pull as a live slider, because how literally you want to read depth is a matter of taste.

🕸️
Constellation field
Nodes are radial-gradient glows with a solid core; edges sit underneath at an alpha derived from the dimmer of their two endpoints, so a link into deep history fades with the thing it points at. A contradicts edge renders as a dashed red line — the one edge type the eye is meant to catch without looking for it.
ui/src/views/constellation/engine.ts · fieldPaint.ts
Settled · 268 lit
🎨
Entity-type legend
Eight typed nodes, each with a dot carrying a box-shadow of currentColor so the swatch glows like the node it describes. Type order is fixed in code, so the legend never reshuffles between loads.
ui/src/views/constellation/index.tsx · ENTITY_TYPE_COLORS
All eight types
personclientprojectsystemconceptdecisionmetricvendor
🔦
LensBar
Tag facets as coloured lenses you swipe across the field: switching one on dims everything without that tag and brightens everything with it. Each chip carries its own count. The dashed con-clear controls sit apart from the lenses on purpose — they are actions, not filters.
ui/src/views/constellation/LensBar.tsx
One lens active
lenses
None active · no clear control
lenses
Hover label & loading state
Two absolutely-positioned mono labels centred over the field. The hover name only shows while nothing is selected, so opening a dossier does not leave a stale label floating behind it.
ui/src/views/constellation/index.tsx · .con-hover / .con-loading
Hovering a node
SteadyStars
Loading
descending…
01

The dossier

Everything the Well knows about one entity, in one scrolling panel: definition, facets, dates, salience, facts with their trajectory status, open questions, linked entities with relationship direction, verbatim excerpts, and the full source list with permalinks. It is the answer to "what does this node actually stand for".

🗂️
Dossier
Slides in from the right edge of the field. Header carries the entity type in its own type colour above the name; Escape closes it (the shell dispatches a general scry:escape and the view decides what "step back" means).
ui/src/views/constellation/Dossier.tsx
Header + definition + facets
client

SteadyStars

Longest-running client engagement (2019→). Retention product; the corpus Sprawler was proven on.

client/steadystarsbizinternal
📐
Dossier meta grid
First seen, last seen, salience, chunk count — the four numbers that determine where the node sits in the field and how bright it is. Reading them next to the node is how you check the encoding is telling the truth.
ui/src/views/constellation/Dossier.tsx · .dos-meta
Populated
first seen
Jun 18, 2019
last seen
Jul 23, 2026
salience
96
chunks
268
Facts list
Each claim leads with a trajectory pill — active, stalled, reversed, superseded — then the statement, then date, confidence and source id in mono. Trajectory is synthesised, not hand-labelled: it is the difference between "here is the state" and "here is where this is going".
ui/src/views/constellation/Dossier.tsx · .dos-facts
Four statuses
  • activeRetention read of 71.4% covers the pilot cohort only, not the account.Nov 21, 2024 · 92% · S-028
  • stalledCohort re-run assigned but not started since the Apr 2025 restructure.Jun 2, 2026 · 74% · S-112
  • reversedRenewal discount ceiling was lowered, then restored at the 2026 cycle.Feb 14, 2026 · 68% · S-095
Open questions
Questions attached to this entity, each with a status pill. A stale question reuses the stalled amber rather than getting a colour of its own — a deliberate reuse, because "nobody has touched this" means the same thing whether it is a fact or a question.
ui/src/views/constellation/Dossier.tsx · .dos-questions
Open + stale
  • openIs the account-wide retention rate ever going to be computed?
  • staleWho signs off the 2027 renewal terms now that ownership moved?
Linked entities
Direction arrow plus the edge type with underscores un-escaped, then the target name in its own type colour, then edge weight. Clicking one selects that entity and lights it in the field, so the panel and the canvas never disagree about what you are looking at.
ui/src/views/constellation/Dossier.tsx · .dos-linked
In and out edges
Excerpt & sources
Verbatim chunk text, truncated at 300 characters with an ellipsis, then the source list with kind, title and a well:// permalink. Between them these two blocks are the whole provenance argument in miniature: here is what was said, here is exactly where.
ui/src/views/constellation/Dossier.tsx · .dos-excerpt / .dos-sources
Excerpt
Moving a third of accounts out of the pilot cohort at the Apr restructure means the old number and the new one are not the same measurement. Say so before anyone quotes it externally.
Sources
02

Graph controls

Obsidian-graph-view style knobs docked into the field, opened from the lens bar. Every one of them is applied to the running simulation rather than rebuilding it, which is what makes the field feel like something you are steering instead of re-rendering.

🎛️
GraphControls panel
Four sections — Forces, Display, Filters, Color groups — in a scrolling aside. Settings live in the persisted store, so a tuned field survives a reload and a route change.
ui/src/views/constellation/GraphControls.tsx
Forces + Display
Graph controls

Forces

Display

Graph filters
Filter by entity type, classification and tag. Filtered nodes leave both the render and the hit-test, and fitView frames only the survivors — so filtering can never strand the field off-screen, which it could before 1.17.15.
ui/src/views/constellation/GraphControls.tsx · GraphFilters
Type + classification + tag
entity type
classification
tag
🖌️
Colour groups
Ordered tag→colour rules where first match wins, so order is meaningful — groups override both the lens colour and the entity-type colour. The add row uses a native colour input plus a datalist of the real tag vocabulary, so a typo cannot silently create a rule that never matches.
ui/src/views/constellation/GraphControls.tsx · ColorGroup
Two rules
  • client/steadystars
  • decision
Empty + add row
  • no groups yet