Skip to content
← All starter build updates

Data starter

Lens

A product analytics workspace for examining traffic, funnels and meaningful trends.

Live on VuraUpdated

Mobile metrics and charts arrive earlier, server reports show their filter snapshot, and cohorts retain a labeled scrollable table. The real bounded report API and all chart ranges passed hosted checks.

Lens: actual released desktop product view after the shared typography refinement.
Preview captured · Explore the product ↗

Build phase

  1. PlannedComplete
  2. BuildingComplete
  3. Local checks passedComplete
  4. In reviewComplete
  5. Live on VuraCurrent phase

This tracks the recorded release phase. The checks below include later findings and ongoing refinements.

Product scope and intended patterns

The following describes the intended reference. Features are not a verification claim; recorded check results below define what has actually been tested.

Client-rendered workspace with explicit static route entries and a real bounded serverless API; demo data boundaries documented.

Learning journal

How to read this starter

Lens is a client analytics dashboard with a serverless report endpoint, synthetic event data and CSV export.

Source map

Analytics store

src/state.js

Filter signals derive active filters, filtered events and aggregate dashboard metrics.

Report API

src/api/report.js

The function endpoint parses filter input and returns aggregate rows for the current selection.

Bounded JSON reader

src/api/bounded-json.js

The parser enforces function payload limits before JSON decoding.

Shared analytics domain

src/data.js

Filter normalization, aggregation, chart semantics and CSV serialization use deterministic fixture data.

Responsive application stylesheet

src/styles.css

Dashboard panels align to their content rather than stretching beside longer charts.

Code patterns worth copying

Treat filters as the source of truth

src/state.js

Dashboard cards, charts, CSV and server reports all follow the same reactive filter shape.

export const activeFilters = computed(() => parseFilters({ range: range(), channel: channel(), cohort: cohort() }));
export const filteredEvents = computed(() => filterEvents(syntheticEvents, activeFilters()));
export const analytics = computed(() => aggregateEvents(filteredEvents()));

Post only the filter contract to the function

src/state.js

The function does not receive DOM state. It receives the small normalized contract it can validate and aggregate.

const response = await fetch('/api/report', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(activeFilters())
    });

Let chart meaning choose the orientation

src/data.js

Revenue by day becomes a time series, while channel comparisons stay categorical.

export function chartSeries(rows, metric, kind = 'category') {
  const ordered = kind === 'time'
    ? [...rows].sort((a, b) => String(a.label).localeCompare(String(b.label)))
    : [...rows];

Block duplicate report refreshes

src/state.js

The result remains a snapshot of its returned filters; the UI labels that snapshot and warns when current controls differ.

if (report().status === 'loading') return;

Real issues and fixes

Chart form should follow data semantics

Problem
The first dashboard drew revenue by day as horizontal bars, making time-series data look like a ranking; later dense 7/14/30 day ranges exposed clipped labels and uneven bar baselines.
Fix
chartSeries accepts a kind, sorts time rows, and returns vertical orientation for day-based trends. The chart CSS uses minmax columns plus a fixed label axis row.
Proof
The overview slices the same chart to the selected 7/14/30 day range, and the build guide records the baseline/axis repair.
Takeaway
A small metadata flag can keep chart components from flattening every metric into the same visual grammar.

Payload limits must count bytes

Problem
A pasted analytics filter body may be larger in bytes than in JavaScript string length.
Fix
Lens uses the shared Uint8Array bounded reader and cancels oversized streams.
Proof
The parser path distinguishes 413 payload failures from 400 malformed JSON before report aggregation runs.
Takeaway
Serverless examples should teach safe request handling next to happy-path charts.

A report snapshot should not impersonate current filters

Problem
Changing controls after a report returned made the server summary look current even though it represented an earlier filter selection.
Fix
Show the filters supplied by the response, compare them with current controls, and disable refresh while a request is pending. Keep cohorts as a semantic horizontally scrollable table.
Proof
Smoke checks report freshness, chart geometry and compact mobile hierarchy without dropping cohort columns.
Takeaway
Label response snapshots explicitly when controls can change independently.

What went smoothly

  • The same parseFilters path feeds client charts and server reports, reducing drift between local and function-rendered numbers.
  • CSV export reads the currently filtered event set, so the download matches the visible table.
  • Shared filter parsing still aligns client and function calculations; freshness copy exposes the remaining snapshot boundary instead of inventing live ingestion.
  • Content-fit dashboard panels and quiet surfaces retain the real dataset chart geometry while bounded headings and 44px native selects unify report routes.

Boundaries to preserve

  • Events are synthetic fixtures, not customer telemetry.
  • The report endpoint computes a response from posted filters; it is not a warehouse query service.

Verification record

Build journal

  1. · Live on Vura

    Shared typography release captured from production

    Published shared typography and responsive control refinements are tied to the exact live deployment and source revision. Actual released captures replace the previous gallery preview; existing product behavior and source-grounded lessons are retained.

  2. · Live on Vura

    Product-depth iteration released and exercised

    Mobile metrics and charts arrive earlier, server reports show their filter snapshot, and cohorts retain a labeled scrollable table. The real bounded report API and all chart ranges passed hosted checks.

  3. · Live on Vura

    Reviewed source ready for release verification

    Unique product identities and deeper workflows are implemented and independently reviewed. Existing releases remain accessible while new source is published and fresh deployments are exercised.

  4. · Live on Vura

    Product-depth iteration in progress

    Compacting mobile analytics hierarchy and clarifying report snapshots and cohort scrolling. The current source and deployment links still identify the previous verified release.

  5. · Live on Vura

    Live corrections verified after independent follow-up

    The7/14/30-day revenue chart has a fixed plot/axis layout, aligned baselines and unclipped columns; every date and amount stays accessible. Filters and report workflows remain live.

  6. · Live on Vura

    Design refinement released for live workflow review

    The analytics view uses a vertical revenue time series, aligned cohort comparisons and a quieter brand rail. Shared filters and the report workflow passed live checks.

  7. · Live on Vura

    Independent live design review started

    The existing public app remains available while a new design review examines hierarchy, typography, navigation and workflow clarity. Actual findings and before/after repairs will be recorded as they are verified.

  8. · Live on Vura

    Hosted reference rechecked after documentation review

    Public source, green CI and the live app were checked together after the clean-machine documentation pass. Lessons and limitations now reflect the implemented code rather than pending pre-release work.

  9. · Live on Vura

    Final source and CI checkpoint verified

    The public source and build reference match the released learning journal, and the source workflow is green. The demo remains live at the same verified deployment; documentation-only refinements did not change application code.

  10. · Live on Vura

    Locked quick start aligned with CI

    The README uses npm ci rather than npm install, so clean-machine setup reproduces the reviewed lockfile before installing Chromium. This documentation-only refinement does not change the hosted app.

  11. · Live on Vura

    Final source and CI checkpoint verified

    The public source and build reference match the released learning journal, and the source workflow is green. The demo remains live at the same verified deployment; README and CI-only refinements did not change application code.

  12. · Live on Vura

    Clean-machine browser setup documented

    The README now installs the locked Chromium engine after npm ci and explains the Linux system-library prerequisite. The hosted application is unchanged; code examples, repair notes and boundaries remain source-backed.

  13. · Live on Vura

    Public template and Vura release

    The reviewed implementation is available from its independent repository and real hosted URL. Detailed code examples and actual repair notes are linked below.

  14. · In review

    Design review cleared; release verification underway

    The local implementation is complete and revised visual evidence has passed review. Source and demo links will appear only after publication and hosted verification.

  15. · In review

    Local implementation ready for review

    The first implementation is available locally. It is not yet a published source reference or a verified Vura deployment.

Implementation lessons

Known limitations

Remaining work and blockers

No release blockers are recorded for this snapshot.

Using this as an agent reference

Read the public README and BUILD.md, reproduce the recorded checks and inspect the source before adapting the starter. A live demo, where available, provides separate deployed evidence.