Skip to content

Dashboard navigation and child pages

The Dashboard (dash.md, alias Dashboard) is the calm place to choose work, review its health, and open supporting collection and task pages. Its navigation sits immediately after # Dash, above ## Tasks, as three labeled rows in exact reading and keyboard order: Review, Work, Browse.

Group Badges, left to right Purpose
Review NEW ยท ROTTEN ยท CROWDED Intake, aging work, crowded notes
Work TODAY ยท PENDING ยท NEXT ยท READY Today's plan and the actionable lanes
Browse PROJECTS ยท REFERENCES ยท BLOCKED ยท STATS โ†— Open supporting collection and task pages

Grouping is navigation only. It never changes the freshness walk, lane semantics, caps, or review sequence, and the Projects collection badge is not the freshness PROJECTS tier.

Work badge colors

TODAY, PENDING, NEXT, and READY use the same count-to-limit colors in daily bob-plan blocks and on dash.md. Counts and limits use exact integer comparisons, never rounded displayed percentages. For an available nonnegative integer count n and positive integer limit L, the colors are:

Condition Color
n === 0 grey
0 < n < 2 * L / 5 blue
2 * L / 5 <= n < 3 * L / 5 green
3 * L / 5 <= n < 4 * L / 5 yellow
4 * L / 5 <= n < L orange
n === L magenta
n > L red

Check zero, strict excess, and exact equality before descending through 80%, 60%, and 40%. Small caps skip bands: cap 1 goes grey โ†’ magenta โ†’ red, and cap 3 goes blue โ†’ yellow โ†’ magenta. Orange first appears at cap 5 (4/5). A NEXT section at 15/15 is magenta even when a larger whole lane makes it over the whole-lane cap; that condition remains informational and does not make the section over.

TODAY uses budget.links for its count and limit. Themes over their cap still override TODAY to red; themes exactly at cap leave the link-based color intact. A missing ledger or invalid count remains unavailable (โ€“). Orange (80% up to the cap) and magenta (exactly at the cap) are presentation states, not lints or over conditions. Magenta marks a lane that is exactly full, and no other Bob chip uses that hue.

Daily bob-plan PENDING/NEXT/READY badges use the same live section counts and colors, including on older daily notes; older notes retain their own TODAY ledger but use current live PENDING/NEXT/READY counts. CLI warnings and navigation notices continue to check the whole lane, including TODAY, while daily bob-plan cap lint lines follow the displayed section counts. An unavailable count remains โ€“ with neutral styling and unavailable accessibility text; it is never converted into numeric zero. Missing ledger data or a missing Pomodoros section remains unavailable, rather than a synthetic 0/limit.

NEW, ROTTEN, and CROWDED share one Review count rule: muted grey with 0 โœ“ when the count is zero, red for every positive count, and โ€“ when unavailable. ROTTEN follows its displayed count even below the escalation threshold or after the upkeep budget is met.

BLOCKED is informational and has no cap. Its count stays available for navigation and uses the same informational accent as PROJECTS and REFERENCES regardless of its size.

Child pages

Root-level notes with hierarchy from frontmatter parent: "[[dash]]":

  • dash_projects.md (alias Dashboard Projects): # Projects, [[dash|โ† Dashboard]], one short active/waiting description, and ![[projects.base#๐Ÿš€ Active & Waiting]].
  • dash_references.md (alias Dashboard References): # References, [[dash|โ† Dashboard]], one short reading-queue description, one empty ```bob-reading-board fence, and ![[refs.base#๐Ÿ”– Reading Queue]]. The board is a read-only kanban (Reading, Next, Ready, Snoozed) drawn from bob ref list JSON; the table follows it. The REFERENCES badge still counts the Reading Queue Base view, not the board. The board's fence, lanes, and keys are in ref.md. The Open Reading Board command opens this page, as Open Stats opens dash_stats.
  • dash_stats.md (aliases Stats, Dashboard Stats): # Stats, [[dash|โ† Dashboard]], one short derived-metrics description, and one empty ```bob-stats fence. The Browse row ends with a label-only STATS โ†— chip (no count) with the same chip chrome, hover preview, and click/Enter/Ctrl-click behavior as the other Browse chips. The block draws the schema-1 report from bob stats; metric meanings, the review journal, and CLI options live in stats.md. The daily-note counterpart is the Day strip.

Neither child carries type: [[project]], and no project or reference note moves. The two .base files keep all views, filters, columns, formulas, grouping, and sorting. The badge always describes the child's default view, even if a visit switches the embedded table elsewhere.

Count scopes

  • PROJECTS links to dash_projects: project notes in the Active & Waiting view, counted once per path. Tooltip: N projects in Active & Waiting. Open Projects.
  • REFERENCES links to dash_references: Markdown reference notes in the Reading Queue, counted once per path. Tooltip: N references in Reading Queue (next, wip, ready). Open References.

A successfully evaluated empty view is 0. Incomplete metadata, a failed source read, or an unrecognized view contract is โ€“ with a short reason in the tooltip and accessibility label. One unavailable collection never hides the other collection or any task badge. Collection size is informational and never turns red.

Source and view contract guard

api.dashboardCollections (namespace v1, top-level api stays v3) mirrors the two default views without a general Bases interpreter. Project type must resolve through Obsidian's link resolver to project.md; a list type never counts. Project status follows Bases containsAny (scalar substring, list exact elements). References use exact case-sensitive status equality, the exact ref/ prefix, and the Markdown extension. No task-only Today, hide, freshness, schedule, or dependency filters apply to either collection.

The plugin parses both .base files with the existing Obsidian parseYaml dependency and validates only membership-affecting structure, including any result limit, tolerating presentation-only changes. A changed filter or renamed view marks that collection unavailable instead of advertising a stale count. Predicate and contract support must be extended together for a future filter change. Base definitions load asynchronously outside the synchronous snapshot(); metadata and vault events refresh open badges after a short debounce, stale async completions are discarded, and widgets are keyed by owning component and kind with cleanup on unload. There is no per-badge polling, and eval, table DOM scraping, and private Bases query APIs are never used.

Tested rolling snapshot bob-cli 41afa14 bob-mac-capture 556bb67 bob-plugins af1e691 Built 2026-10-24T22:34:13Z (zensical) build.json