Home (apps/renderer/src/routes/index.tsx) is the page the app opens on. It shows the getting-started checklist while that has anything to say, then a dashboard of widgets. A profile with no trackables of its own shows the checklist and a way to create the first one instead.
The trackable card
Every direct and derived trackable has a card, TrackableCard (components/home/TrackableCard.tsx), and the card carries both jobs, looking and logging:
- The header names the trackable, linking to its page, and says what the day set in the top bar holds for it: its answer that day (“Today 07:10”, “Today Nothing”, a value), which on a direct trackable’s card opens the day’s entries to edit; or “Not logged today · last Good” for a direct trackable and “No reading” for a derived one; or “No entries yet”. The streak set up on the trackable (Achievements), when it has one, shows as a flame once it runs past one day, while streaks are switched on. A direct trackable’s card has a Log button, which opens the entry panel in a dialog; a derived one is computed and has none.
- The tabs are the trackable’s visualizations in its order, less the table and a chart with nothing to plot, followed by every visualization of several trackables placed on it. They always fill their line; the ones that do not fit go behind the library’s More menu. Which tab is open is kept per trackable in the
home:cardViewsetting, so a card stays where it was left. Everything else is the visualization’s own, so the card asks the same question of the same days as the trackable’s page. - The body is the open visualization drawn as the editor draws it (
VisualizationBody), its headline first, with the trackable’s target bar when it declares one. A Calendar here is the contribution grid of the period, as on the trackable’s page (Calendar Drill-down). Its Reading picker and a calendar’s scale change only this card while it is open (Which controls save). The drawing measures its cell and fills it, so a resized card redraws rather than scrolls. - Controls: beside the tabs, the settings button, which opens the visualization editor on the open tab; under them, a Reading picker and, on a calendar, its scale, which change what the card shows. Whether they also save, in the design and in the code, is set out once, in Visualizations (“Which controls save”).
A visualization pinned to Home is a card of its own beside the trackable’s, TrackableCard with only set: it shows that one visualization with no tabs, and its header names it (“Sleep · Timeline”).
The dashboard
Dashboard (components/home/Dashboard.tsx) lays the widgets out on a react-grid-layout grid: 12 columns from 1024 px, one stacked column below, rows of 30 px. Each widget sits in a library Card, which is a size container, so its contents can respond to the cell they are given rather than to the window.
Arranging is behind a toggle, Customize and Done, so browsing never moves anything. While customizing, any widget can be dragged and resized, its contents stop taking clicks so a drag never presses a button, each widget has a remove button, Add widget lists the hidden widgets under headings (Trackables, Overview, Visualizations), and Reset returns the default layout and the default set. Reset clears the stored settings rather than writing the defaults back, so a dashboard that was reset reads as never customized (the getting-started step for making Home your own reads that).
The widget catalog, with its ids:
| widget | id | shown on a fresh dashboard |
|---|---|---|
| a card per direct or derived trackable | card:<trackable id> | the first six, and every trackable whose entries are amounts of catalog items |
| a trackable’s visualization pinned to Home | viz:<trackable id>:<kind> | while pinned |
| a visualization of several pinned to Home | visualization:<id> | while pinned; its title opens it |
| Consistency: entries a day over the last 13 weeks | chart:heatmap | yes |
| a scatter of the first two number trackables, joined by day, days on hold left out | chart:scatter | yes, when there are two |
| Recents: the six latest entries, an entry holding others one row saying how many | recents | yes |
A pinned widget shows on Home whether or not the chosen set lists it, and removing it from Home unpins it. A widget whose trackable or visualization no longer exists drops out.
The layout, per breakpoint, and the chosen widgets are kept in the profile’s database, in the app_setting rows dashboard:layout and dashboard:widgets, through useSetting, so they survive a restart and travel with the profile file. Sync leaves them out, with home:cardView: they describe one screen rather than the person, so a phone and a desktop each keep their own arrangement (LOCAL_SETTING_KEYS in packages/core/src/sync-capture.ts). A saved position is used where it exists and the default packing everywhere else, so a new widget slots in. migrateWidgetId (components/home/dashboard-migrate.ts) maps the ids of earlier widget kinds to today’s when a stored set is read.
The grid gives way on a narrow screen by stacking; the app’s shell handles the rest of a phone’s width (see App Shell).
Related
Visualizations · Calendar Drill-down · Visualization Persistence · App Shell · Frictionless Capture