Atrium
A privacy-first AI assistant workspace. Streaming chat, memory inspection, tool traces, persona switching, voice.
The problem
The privacy-first AI assistant category is a real 2026 product lane, not a one-vendor experiment. Swisper AI in Zurich, Mistral's Le Chat, and Proton's assistant all share the same UX shape: streaming chat as the front door, a memory surface, tool traces for trust, persona switching, and a visible privacy story. What is missing in the senior React hiring pool is a reference UI that implements the whole shape end to end against a real CI pipeline instead of a slide deck.
Goals
- Ship the full assistant UX shape (chat, memory, traces, personas, voice) as a single coherent product
- Keep the project front-end only so it ships in weeks, not months, and stays a pure FE artifact
- Drive every streaming token, tool call, and memory write through a deterministic mock layer so the UX is the hero
- Hold a real CI gate: typecheck, lint, Vitest, Playwright, build on every push
- Phase the build so each phase is independently demoable
The solution
- App shell with top bar, left rail, main column, and a right-side memory inspector that defaults open on large screens
- Design tokens as a TypeScript source of truth with runtime CSS-var injection plus Tailwind theme refs, so light, dark, and system themes share one set of values
- Deterministic SSE simulator with a step-based fixture format (tokens, tool, memory, wait) that doubles as the contract a real backend would have to match
- Research Analyst persona wired end to end with search_web, fetch_url, and summarize, each call landing in the inline trace drawer with input, output, latency, and status
- Memory inspector with per-fact provenance, dedupe by id or key, a forget control, and a purge-all action
My role
- → Solo architect and engineer from requirements to deploy
- → Owner of the design tokens pipeline, mock-layer-as-contract, and CI gates
UI direction
One opinionated theme in light, dark, and system modes, built from design tokens in TypeScript so the same values drive runtime CSS variables and Tailwind classes; the chat column anchors the layout while the memory inspector and tool trace drawer are first-class surfaces, not overlays.
User flows
Research Analyst prompt to memory fact
- 1 User types a research prompt in the composer
- 2 SSE simulator streams tokens into the message list while the trace drawer shows a running tool call
- 3 Tool call completes, latency and status land in the trace timeline
- 4 A new fact appears in the memory inspector with its provenance line
- 5 Forget control on the fact wipes it and re-renders the inspector
Persona switch
- 1 User opens the persona menu in the left rail
- 2 Research Analyst is active; Code Assistant and Travel Planner are visible but marked Phase 3
- 3 Switcher silently rejects unavailable personas so a leaked URL cannot drop into a broken state
- 4 Switching personas resets chat, memory, and trace stores together through the chat store
Screenshots
Click any image to open at full size.
Key learnings
- Design tokens as TS source of truth plus runtime CSS-var injection is the cleanest way to keep Tailwind, runtime themes, and Storybook in sync
- A step-based fixture format (tokens, tool, memory, wait) doubles as the real backend contract, so Phase 6 swap is a backend job, not a front-end rewrite
- Cross-store reset through the chat store keeps memory, traces, and chat in lockstep without coupling the simulator to any store
- Right panel defaulting open on large screens trades a tiny bit of first-load density for users actually discovering the memory surface
Want something like Atrium?
I'm open to senior contract work. Let's talk about what you're building.
Get in touch