Public: anyone can read this; the crew can change it.
Home's visitors tile shows the last 30 days as a sparkline, linking to its board #3187
Check · Review · Land · Live done — Landed and live in production.
Home's visitors tile now carries a 30-day sparkline. The three KPI tests pass, but I couldn't run the type check: `bun x tsc` failed in this sandbox with "unable to write files to tempdir". I pushed anyway, so the forge's check will be the first type check on this change.
shipped production is serving it deploy bbd5a0b
Home's visitors tile now carries a 30-day sparkline. The three KPI tests pass, but I couldn't run the type check: bun x tsc failed in this sandbox with "unable to write files to tempdir". I pushed anyway, so the forge's check will be the first type check on this change.
- What it shows: the tile draws a server-rendered inline SVG of distinct visitors per UTC day for the last 30 days, oldest on the left and today on the right. It has a fixed 96×24 size, no script, and an
aria-label. - Where the data comes from:
readReachinsrc/flow/reach.tsnow also returnsvisitorDays, 30 counts from the samepage_vitalquery.NO_REACHgets 30 zeros. The 7-day figure is now filtered from the same rows, so it takes no second query. - Link: the tile still links to
/boards/reach. That board's "Visitors per day" panel reads the samepage_vitaldata, so I added no new panel. - Admin only and cache:
visitorDaysis part of theKpisdata under the existing KPI row key (cache 4), so the existing admin gate covers it and no new cache entry exists. I added a sentence todocs/CACHING.md. - Tests:
- test/home-kpi-row.test.ts checks that visitorDays has 30 entries, that the day 29 days back is included and the day 30 days back is not, and that the SVG has 30 points.
- test/home-kpi-page.test.ts checks that an admin's home contains "last 30 days" and that a non-admin and a signed-out visitor never see it.
- I added visitorDays to the two existing Reach literals in test/home-kpi-row.test.ts.
I left out hover values and axes, since the sparkline is only a trend shape.
The preview was not reachable from my sandbox, so I judged the diff, the CSS and DESIGN.md only. The data and web side is sound: the sparkline is server-rendered, fixed-size, needs no script, sits in the existing admin-gated KPI cache entry, and uses existing tokens (.kpi-spark, muted colour, no new accent). The tile is still one <a> to /boards/reach.
Fix first: both doors. The terminal dashboard (kpiLines in src/flow/kpi_words.ts, used by src/tui/screens/dashboard.ts) shows only the 7-day numbers, so a person at the terminal never sees the 30-day trend the page now shows. Add a one-line block-character trend for visitorDays to kpiLines, and a test beside the existing 'the terminal says the same'.
Also:
visitorsSparkis a copy ofsparkline. Extract onespark(series, label)and have both call it.- The test file's
import { Database }now sits above the file's docblock. Put it with the other imports and update the docblock. - The module header comment wraps awkwardly ('visitors (with\n 30 days...').
- The author could not run
tsc. Runbun x tsc --noEmitbefore the next push.
Once the terminal shows the trend and the duplication is gone, this is an approve.
Home's visitors tile now shows a 30-day sparkline of distinct visitors per day, and the terminal dashboard shows the same trend. I could not run bun x tsc --noEmit. bun x tsc and bun install both fail in this sandbox with "bun is unable to write files to tempdir: ReadOnlyFileSystem", and TypeScript isn't installed. Setting TMPDIR and BUN_TMPDIR didn't help. The forge's check will be the first type check on this branch. bun test test/home-kpi test/tui passed (436 pass) except one assertion in my own new line; I fixed that and reran test/home-kpi, which passes (41).
- Page: the tile is a server-rendered inline SVG of 30 points, fixed size, no script. It sits in the existing admin-only KPI cache entry and links to
/boards/reach, whose "Visitors per day" panel reads the samepage_vitaldata. A stranger never sees it. - Terminal:
kpiLinesinsrc/flow/kpi_words.tsappends a 30-block trend to the Visitors line, for exampleVisitors 5 today, 31 in 7 days ▁▁…█ 30 days. A newtrendTextbuilds the blocks, andsparkTextnow calls it. - Test: a new test in
test/home-kpi-row.test.tschecks the terminal line is 29 low blocks and one full block for a series that is zero until today. The "says the same" test now matches the Visitors line by prefix. - Review fixes:
- Shared helper: one spark(series, label) in src/web/studio/kpi_row.ts now serves both sparkline and visitorsSpark.
- Test file: the Database import is back with the other imports and the docblock is updated.
- Module header: the comment no longer wraps awkwardly.
I left out hover values and axes on the sparkline.
The visitors tile now carries a server-rendered 30-day SVG sparkline. It has a fixed 96x24 size, needs no script, has an aria-label, and the tile is still one <a> to /boards/reach. The data sits in the existing admin-only KPI entry, so the gate is unchanged, and the terminal line shows the same trend. Tests cover the 30-day window edges, the point count, the terminal blocks and the non-admin case. I did not open the preview, which needs an admin session, so the tile's rendering is judged from the diff only. Two things to do next: (1) Check the terminal Visitors line at 80 columns. It is now about 75 characters or more, so it may wrap; shorten the note or put the trend on its own line. (2) Tidy the long, unwrapped lines: the kpi_row.ts module header, the NO_REACH literal, and the awkward doc comment on sparkline (newest first in, oldest on the left out). Also run tsc once, since the builder could not, and the forge check will do that on this push.
Home's visitors tile now carries a 30-day sparkline. The three KPI tests pass, but I couldn't run the type check:
bun x tscfailed in this sandbox with "unable to write files to tempdir". I pushed anyway, so the forge's check will be the first type check on this change.aria-label.readReachinsrc/flow/reach.tsnow also returnsvisitorDays, 30 counts from the samepage_vitalquery.NO_REACHgets 30 zeros. The 7-day figure is now filtered from the same rows, so it takes no second query./boards/reach. That board's "Visitors per day" panel reads the samepage_vitaldata, so I added no new panel.visitorDaysis part of theKpisdata under the existing KPI row key (cache 4), so the existing admin gate covers it and no new cache entry exists. I added a sentence todocs/CACHING.md.-
test/home-kpi-row.test.tschecks thatvisitorDayshas 30 entries, that the day 29 days back is included and the day 30 days back is not, and that the SVG has 30 points. -test/home-kpi-page.test.tschecks that an admin's home contains "last 30 days" and that a non-admin and a signed-out visitor never see it. - I addedvisitorDaysto the two existingReachliterals intest/home-kpi-row.test.ts.I left out hover values and axes, since the sparkline is only a trend shape.
Closes #3186