A visualization is kept as the question, not the answer: a declarative spec of what it reads, how it transforms it and how it draws it, stored as a row and drawn again from the entries every time it is opened. That is what turns a one-off look into something you keep coming back to: “Weight vs Water”, built once, is current every time it is opened, and changing it never changes what was logged. A kept visualization is not a different kind of thing from one being edited, which is why there is no separate term for it; this note is titled for the mechanism.

The row

Every visualization is a row of one table, view in SQLite and visualization in the Drizzle schema (packages/core/src/schema.ts): a name, an opaque JSON spec, pinned (on Home as a card of its own), an optional trackable_id and a sort_order. The table knows nothing of the spec’s shape, so a new chart or a new transform never costs a migration.

a trackable’s taba visualization of several
trackable_idthe trackablenone
specVisualizationSpec (packages/core/src/value-schema.ts), owned by coreSeriesSpec (apps/renderer/src/hooks/useVisualizations.ts), owned by the renderer
read and written byTrackableVisualizationRepository (trackable-visualization-repository.ts), through the trackableVisualizationRepository (visualization-repository.ts): list, listPinned, getById, create, update, setPinned, remove
ordersort_order, the trackable’s tab ordernewest first

A trackable’s tabs travel with the trackable. The repository attaches them on read as Trackable.visualizations, and a trackable payload’s visualizations writes them, in order; a payload that leaves them out keeps them. A kind the trackable already has keeps its row, so the row’s id holds still for sync, and a kind no longer listed is deleted. They are deleted before their trackable is, since SQLite cannot add a cascade to a column added later, so a trackable’s visualizations go where it goes: deleted, exported and synced with it. What a VisualizationSpec holds is set out in Visualizations.

A visualization of several is a SeriesSpec, version v: 1:

fieldholds
serieseach series’ dotted id, a trackable, a Reading, a record field by its reduce or a text read for a word (see Editor for Several Trackables)
vizthe chart: scatter, line, matrix, distribution, grouped, histogram, heatmap or timeline
smooth, lagthe 7-day mean, and the days the second series is shifted
controlsthe series held constant for a partial correlation
bucketweekday or month, for a grouping by time
period, periodFolddays grouped into weeks or months, and how their days fold
dropStopwords, skipOnHoldcommon words kept, days on hold left out
shownOnthe trackables it is a tab on
colorsa series’ own colour, by series id

Optional keys are left out at their default, so a spec stays small and readable. A series refers to a trackable by its stable id, so renaming a trackable changes nothing; an id that no longer resolves drops out of the series, so a deleted trackable leaves the visualization drawing what remains rather than failing.

Keeping one

The editor’s Save writes the visualization of several it was opened from; Save as new makes another, named for what it shows rather than for the one it came from, since two under one name read as a duplicate. A new one’s first Save opens what it saved, so its next Save updates it, and a toast says which happened (“Saved”, “Saved as”). Opening a saved one restores the editor field for field from its spec and its row’s pinned, once, so later edits are not undone. A trackable’s tab is saved from the editor’s one-trackable panes with the trackable itself.

Where one shows is part of what is saved. Shown on ticks Home, the row’s pinned, and each trackable the series read, its shownOn; a trackable it no longer reads is dropped from shownOn on Save. On a trackable it is a tab after the trackable’s own (placedOn), as long as one of its series still reads that trackable. Pinned, it is a card on Home.

Drawing one

SeriesVisualization (apps/renderer/src/components/series/SeriesVisualization.tsx) draws a visualization of several from its spec wherever it shows: the list at /visualizations, a Home card and a trackable’s tab. It resolves the series again and reads the selection and its chart data through the same seriesSelection and chartDataOf the editor uses, so a spec means one thing in both places, a text read for a word included. It draws the chart the editor opens on: a saved chart the selection no longer offers draws the one effViz clamps it to. It draws the chart and not the statistics: a card has no significance verdict, and controls is kept but no partial correlation shows outside the editor. What is kept is the chart’s question; the reading of it is the editor’s.

The list at /visualizations shows each one drawn, with its title linking to the editor, a Pin to Home toggle, and Delete, which asks first, because a deleted visualization has no undo and goes from every trackable and from Home. New visualization opens an empty editor. A name is set when a visualization is first saved and is not edited afterwards.

Nothing computed is stored, here or anywhere: a spec is re-run against the entries as they are.

Editor for Several Trackables · Visualizations · Home · Data Model · Synced Databases