Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Zaati OS is an open-source, private-by-default personal operating system. Schedu

You choose the LLM. You own the data. You control the deployment. Zaati OS has no hosted account, required telemetry, central database, or platform fee.

Explore the [three populated dashboard examples](examples/README.md), with local screenshots, forkable JSON compositions, and a documented [design system](docs/design-system.md). Run `npm run examples` after installing dependencies.

<p align="center">
<img width="720" height="405" alt="Animated preview of the Zaati OS synthetic dashboard" src="https://github.com/user-attachments/assets/efa34769-a201-433e-851e-c407b33580f4" />
</p>
Expand Down
30 changes: 29 additions & 1 deletion docs/design-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,35 @@ Charts are explorable rather than decorative. Line points and bars expose the sa

Use semantic tokens such as `background`, `card`, `muted`, `primary`, `warning`, and chart tokens. Do not hardcode provider or source colors inside components.

## Accessibility
## Dashboard composition recipes

The [populated examples](../examples/README.md) are executable composition references. They use the production renderer and existing snapshot schema. Personal data never belongs in examples or screenshots.

| Element | Rule | Reason |
| ------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| Primary metric | First metric uses `primary` / `primary-foreground`; values use 24–32px tabular numerals | Establish one visual anchor without a marketing hero |
| Supporting metrics | Semantic accent edge, 9% tinted surface, full-contrast labels | Separate measures while preserving legibility |
| Cartesian charts | Two-column span preferred; 480px minimum canvas with contained horizontal scroll | Keep tick labels readable at 320px |
| Donut | Stack inside narrow cards; switch to side-by-side at a 480px container | Respond to the card rather than viewport width |
| Exact values | Native `View data` disclosure, formatted table; full donut legend values | Make precision available to touch and keyboard users |
| Evidence | Keep dates, stale status, and assumptions adjacent to the decision | Avoid implying live or complete data |
| Tables | Prefer two columns or full width for prose-heavy rows | Avoid unreadable evidence columns |

Categorical chart colors distinguish series, not good and bad. Line styles also differ so color is not the only encoding. A numeric increase is not automatically a favorable outcome; producers should supply a change only when its meaning is clear. Metric emphasis indicates priority, not health.

### Motion and interaction

Entrance motion runs once, with no perpetual pulsing or autoplay. Blocks settle over 320ms; line and progress reveals use a 520ms clip wipe so the data's geometry never stretches sideways; bars grow over 480ms. Chart interaction changes emphasis without moving the measured endpoint. Static cards remain in place on hover. Reduced-motion preference reduces animations and transitions to 0.01ms.

Donut legend buttons toggle persistent selection with click, tap, Enter, or Space. Hover and focus provide temporary inspection; `aria-pressed` describes selection only. Long category names wrap. The center uses compact notation; full values remain in the legend. Cartesian data is also available through a native disclosure, with no pointer precision required.

### References and boundaries

Composition research: [shadcn dashboard-01](https://ui.shadcn.com/blocks), [chart gallery](https://ui.shadcn.com/charts/area), and [chart documentation](https://ui.shadcn.com/docs/components/chart), reviewed September 5, 2026. Adopted the strong metric row, dominant visualization, contextual table, and progressive disclosure patterns. Zaati retains its owned shadcn-compatible primitives and lightweight SVG renderer; it does not add Recharts or copy reference code.

Palette changes belong in semantic tokens or validated instance themes. Snapshots select content, spans, and audited block kinds, never CSS, JavaScript, SVG, or arbitrary component trees. The showcase build is explicit and ignores local private configuration. Normal personal builds retain the existing behavior.

## Accessibility verification

All controls need accessible names, keyboard focus, usable touch targets, and sufficient contrast. Color cannot be the only status signal. Charts need an accessible label and should have table or narrative evidence in the snapshot when exact values matter.

Expand Down
48 changes: 48 additions & 0 deletions docs/ui-audit-showcase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# UI audit: template dashboard showcase

Reviewed September 5–6, 2026. Scope: `zaati-os` only. No private dashboard, source snapshot store, scheduled task, or deployment configuration was changed.

## Intent

A reader should find the leading answer, understand its evidence, and identify a concrete next step. Visual contrast and motion support that sequence. Examples must be useful to a new forker without personal knowledge or new renderer code.

## Findings and implementation

| Finding | Resolution |
| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| Metrics had nearly the same weight as labels | Larger tabular values, primary-color leading metric, semantic accent edges and tinted supporting tiles |
| New tinted tiles initially reduced label contrast | Full-contrast tile labels; verified in the browser before capture |
| Static cards lifted on hover as if clickable | Removed lift while preserving quiet border feedback |
| Line entrance stretched the measured geometry | Clip reveal keeps points in their correct coordinates throughout motion |
| Bar hover moved measured endpoints | Removed positional scaling; highlight changes emphasis only |
| Narrow SVG charts shrank tick labels excessively | Minimum 480px chart canvas, keyboard-focusable contained scroll region |
| Exact-value tables were screen-reader-only | Native `View data` disclosure exposes formatted evidence to everyone |
| Donut layout responded to viewport, not card width | Container query switches to horizontal composition only when the card has space |
| Donut legend did not have persistent touch selection | Click/tap toggle and native keyboard activation, separate selected and inspected state |
| Large donut totals and long labels could collide | Compact center value, full legend values, wrapped category names |
| Example rows left gaps or squeezed tables | Revised spans and reading order; full-width holdings/work tables and wider source evidence |
| Work distribution made the neighboring list excessively tall | Wide donut with side-by-side legend, narrow action list |
| Headline metrics lacked supporting example evidence | Removed unsupported goal-pace, monthly-change, and due-count headlines in showcase fixtures |
| Daily schedule contradicted its buffer and reply windows | Buffer starts at 15:30; urgent reply is scheduled before the protected 08:30 focus window |
| Screenshots could race lazy loading and animations | Wait for page readiness, chart resolution, and animation completion |
| Historical demo screenshots looked entirely expired | Review clock pinned to the latest synthetic snapshot; actual stale-source warnings remain |
| Public captures lacked an explicit synthetic-only guard | Screenshot capture rejects datasets not marked entirely synthetic |
| Forkers lacked isolated populated examples | Three complete envelopes under `/examples`, explicit local runner, schema/privacy validation and isolation regression test |

## Verification protocol

The full default-page pass also caught low contrast on a negative change in Weekly review. Change values now use readable neutral text, since a negative number alone does not imply a bad outcome. The money showcase reconciles total cash runway to the monthly living budget (22,600 / 3,100 = 7.3 months), and separately measures the emergency reserve (15,800 / 3,100 = 5.1 months).

The production build is exercised in local Chromium at 320, 390, 768, 1024, and 1440 CSS pixels, in light and dark modes. The showcase covers onboarding, component lab, daily, money, and work views. The normal build additionally covers agenda, inbox, news, and review. Automated checks include axe WCAG A/AA rules, document overflow, chart disclosure, selection toggling, keyboard Space activation, reduced-motion CSS, mobile navigation, theme studio, and prompt drawer. The component catalog is also checked with ocean, plum, and sand palettes in both themes.

Full-page PNGs in [examples/screenshots](../examples/screenshots) are rendered from synthetic envelopes with the production components. Visual inspection covers hierarchy, wrapping, chart legibility, card balance, source dates, and meaningful next actions. The examples use the default sage palette; alternative palettes remain user-selectable.

The repository gate is `npm run check`: formatting, lint, repository rules, schema and privacy validation, production build, coverage, tutorial, performance budgets, and browser accessibility. The separate showcase capture command is documented in [examples/README.md](../examples/README.md).

## Practical limits

The full repository check passed with 53 tests. Coverage was 97.57% lines, 86.68% branches, and 94.81% functions. The normal demo build measured 111 KB JavaScript, 10 KB CSS, and 87 KB dashboard data, all gzip and within the existing budgets. Screenshot evidence includes desktop and mobile, light and dark, for all three examples.

This audit uses Chromium emulation and browser automation, not a physical-device lab or a human screen-reader session. Axe is a baseline, not accessibility certification. At narrow widths, charts and wide tables intentionally scroll within their cards; the page itself must not overflow. Financial values are illustrative and formatted/rounded for display. No live account data or remote connector was used.

The public template's security and snapshot boundary is unchanged. These improvements add no chart library, external font, telemetry, or arbitrary snapshot-controlled markup. Design decisions and adaptation rules are maintained in the [design system](design-system.md).
43 changes: 43 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Dashboard examples

Three complete, synthetic dashboards rendered by the production shadcn-compatible components. These are starter compositions for forkers, not personal records or live feeds.

```sh
npm ci
npm run examples
```

Open the local Vite URL with one of these query strings:

| Dashboard | URL query | Reading order |
| -------------- | ------------------------------------------------ | --------------------------------------------------------------------- |
| Daily cockpit | `?view=overview%3Adaily&at=2026-08-24T07:35:00Z` | Available focus, attention pattern, today's schedule, next actions |
| Money overview | `?view=money%3Apulse&at=2026-08-24T07:35:00Z` | Tracked value, scenarios and allocation, monthly plan, exact holdings |
| Work focus | `?view=work%3Afocus&at=2026-08-24T07:35:00Z` | Work in progress, state distribution, next moves, delivery evidence |

`at` fixes the review clock to the fixture date. Without it, historical examples correctly appear stale. Every screen retains source dates and uncertainty. Scenarios are illustrative, not predictions.

## Adapt an example

Complete envelopes live in `snapshots/{domain}/{source}/2026-08-24.json`. Keep the envelope and use the existing eleven block kinds. Change content, block order, spans, and instance theme before considering renderer changes. Keep a two-column chart next to a one-column supporting block; use full-width tables when text needs room. Put the most important metric first because it receives the high-contrast treatment.

Examples are validated by `npm run data:validate`, including public/synthetic privacy requirements. `npm run examples` explicitly ignores private snapshots and local instance configuration. It builds the shared ignored `public/data/dashboard-data.json`, so stop other local dev servers first. Run `npm run dev` or `npm run build` afterward to restore normal instance selection. Never set `ZAATI_EXAMPLES=true` in a personal production deployment.

No new block types, provider integration, remote fonts, or chart dependency are required. Locale, currency, time zone, density, and palette remain instance settings. Do not mix fixture currencies when adapting examples.

## Reproduce the screenshots

```sh
ZAATI_EXAMPLES=true npm run build
ZAATI_CAPTURE_SCREENSHOTS=true ZAATI_SCREENSHOT_DIR=examples/screenshots npm run accessibility:check
```

Install Chrome or set `CHROME_PATH`. Capture rejects non-synthetic datasets, waits for lazy charts and entrance animations, then audits five widths in both themes. PNGs are actual local Chromium renders, not mockups.

| Example | Desktop light | Desktop dark | Mobile |
| ------- | -------------------------------------------- | ------------------------------------------ | ------------------------------------------- |
| Daily | [Light](screenshots/overview-1440-light.png) | [Dark](screenshots/overview-1440-dark.png) | [390px](screenshots/overview-390-light.png) |
| Money | [Light](screenshots/money-1440-light.png) | [Dark](screenshots/money-1440-dark.png) | [390px](screenshots/money-390-light.png) |
| Work | [Light](screenshots/work-1440-light.png) | [Dark](screenshots/work-1440-dark.png) | [390px](screenshots/work-390-light.png) |

See the [design system](../docs/design-system.md) and [UI audit](../docs/ui-audit-showcase.md).
Binary file added examples/screenshots/money-1440-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/money-1440-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/money-390-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/money-390-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/overview-1440-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/overview-1440-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/overview-390-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/overview-390-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/work-1440-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/work-1440-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/work-390-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/screenshots/work-390-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading