Skip to content

COROS AI · Case Study

Designing an AI that remembers you

A page that reflects a user's coaching history back to them at an early-stage AI startup, designed end to end from the information architecture to the prompts behind every card.

Prompt EngineeringUX/UIDesign EngineeringProduct Design
Role
Product Designer · Prompt engineering · Prototyping · Co-implementation
Team
Founder/CEO · 2 engineers · 2 designers
Timeline
April 2026 – Present
Tools
Figma · Claude Code · Streamlit · HTML/CSS/JS · Prompt engineering
← Back to COROS AI

My World, at a glance

The My World page: a featured band with the My Breakthroughs donut, Latest Breakthrough, and Coaching Provocation cards above the Reminders widget.
A session detail page ('Overcoming avoidance to write resume') with summary, entry and exit moods, a commitment, a breakthrough quote, and relationships.
The My Breakthroughs donut showing 20 breakthroughs by dimension, beside the latest breakthrough quote.
The Coaching Provocation card: 'Identity is built, not discovered,' ending in a question back to the user.
The Reminders widget mid-celebration: confetti falling as a reminder is checked off.

The problem

Coaching that evaporates

COROS is an AI life coach. Users have genuinely transformative conversations: they name a fear, make a commitment, see something about themselves for the first time. Then the session ends and all of it vanishes into chat history.

My World reflects that history back. The brief I wrote for it became the team’s north star:

A mirror, not a filing cabinet.

The design brief, and the team's north star

Not a tracker, not a stats dashboard, but a surface that shows you the pattern of your own transformation and invites you back into conversation. That one sentence settled dozens of downstream debates: no page-level filters, no scores or streaks, a ~100-word cap per widget, and every element ending in an on-ramp back to coaching.

And this wasn’t UI over an API. Every card’s content is generated by LLM prompts I wrote, so I owned three layers at once:

  1. The information architecture: how raw conversations become structured, browsable objects.
  2. The interface: a responsive page of independent widgets.
  3. The prompts, plus the QA tooling: the generation layer behind every field on screen, and the harness that validates it.

Layer 1 · Architecture

How the AI organizes what it remembers

I co-authored the product’s design and implementation document through four versions, which engineering builds from directly. Its core distinction: a Session is an event: one conversation, factually summarized into a structured object with summary, moods, breakthrough, reminders, and relationships. A Topic is a territory: a situation the user keeps returning to, like “Navigating a difficult conversation with dad.”

The rule I fought hardest for: a topic is a situational territory, never a feeling. Early model outputs kept producing topics like “Self-worth”, which is navigationally useless and subtly harmful. I codified this as the identity-vs-texture rule: feelings may color a summary, but never become the title. It now governs the topic prompts and the two-stage detection pipeline (embedding search feeding an LLM match decision).

The hierarchy in navigation: My World → a topic's territory → one session's detail.

I also framed My World as a federated portal: each widget ships independently with its own prompt, logic, and documented rationale, so engineers could build one widget without waiting on another to stabilize.

Layer 2 · Interface

Three iterations that mattered

The main view

A featured band of three reflective cards (My Breakthroughs, Coaching Provocation, Latest Breakthrough) above a full-width stacked Topics list, filterable by seven life dimensions (Family, Work, Self, Health, Meaning, Belonging, World) and by status. Topics are never tiled as a grid; each gets room to breathe. A cross-page filtering concept tested well, but I argued to defer it and hold a stricter rule: filters belong to individual widgets, not the page.

The page, top to bottom: featured band, reminders, topics.

Combining two key widgets

We had two separate widgets, and the donut was under threat from a line-chart alternative. Instead of choosing, I merged them into one widget with two modes and specced the full state machine:

  • Mode A: donut inert, the panel shows the newest breakthrough, arrows walk the whole history.
  • Mode B: clicking a segment filters the panel to that dimension, and auto-advancing past a dimension’s last breakthrough moves the donut’s live selection in real time, traversing dimensions in palette order.

I resolved every edge case before handoff: backward symmetry, wrap behavior, and empty dimensions absent from the ring and the traversal alike. The merge settled the chart debate and delivered cross-filtering as an intra-widget interaction, honoring the no-page-level-filters rule.

Both modes of the state machine, including the donut's live selection following auto-advance across a dimension boundary.

The Reminders widget

When the team reframed commitments into reminders (which can also be stances: “Notice the voice of fear and keep going anyway”), I designed the widget that carries them: reminders pooled across all sessions, newest first, paginated inside the widget. Two actions, Done and Delete. Delete exists because these are AI-generated and can be wrong, so users need an honest way out. Both update shared state across the widget and the originating session.

One detail I’m proud of: an unchecked reminder re-enters at its original chronological position, so position always encodes creation order. I flagged the engineering implication myself: the creation timestamp must live in shared state, not be derived from visible position, and it went straight into the build spec.

A reminder checked off: completion gets confetti.

Simplifying a cluttered screen

Alongside these, I ran repeated decluttering passes on the topic card and detail views in weekly triage with the founder: labels stripped to inline values, “Archive” renamed to “Box” to fit the product’s language, sticky bottom CTAs held because users decide to continue only after reading. The whole design is responsive, specced with breakpoint behavior across desktop and mobile rather than as two designs.

Widget-level filtering: the topics list narrowing by life dimension.

Layer 3 · The AI

Prompts, testing, and QA

Prompt engineering as design work

I wrote and iterated the prompts that generate everything on screen: the session summary (six versions, now the canonical data artifact), the topic summary (seven versions), topic detection, and the coaching invitation prompt now in progress. The craft is closer to spec-writing than copywriting. Silence in a gate is an admission: if you don’t explicitly name an exclusion with examples, the model walks through it.

The breakthrough field shows the stakes. A breakthrough shown back to a user is a claim about their life; get it wrong and you manufacture a false memory. I built it around a strict ownership gate (it can only reflect what the user actually said or agreed to), explicit guardrails against language that overstates or fictionalizes change, and a required register that describes rather than diagnoses.

The Coaching Provocation widget: 'Identity is built, not discovered,' a synthesis across recent sessions that ends in a question and a Revisit action.
What the invitation prompt produces: a provocation synthesized across recent sessions, ending in a question, and an on-ramp back to coaching.

Building my own testing tools

To validate all of this, with the development team, I built out our Streamlit playground: a QA harness that runs real conversation transcripts through the entire My World pipeline (session summary, two-stage topic detection, and topic summary), exporting structured JSON. I later added an Invitation tab for the provocation prompt with a five-line additive diff.

The Streamlit playground: real transcripts in, editable prompts, structured JSON out, with a per-session results table for field-level compliance checks.

My method: run a batch of ~20 sessions, then check every output field against the prompt’s own rules. A recent run surfaced five must-fix issues: each traced to a specific missing clause and fixed with a surgical insert, not a rewrite.

Co-implementation

From mockups to shipped code

Midway through, I stopped ending my work at the Figma handoff. Using Claude Code, I began implementing widgets on localhost and shipping working builds to engineers for review.

The technique that made it work: I write implementation prompts the way I write design specs. The combined breakthrough widget went to code as a complete state machine, with every assumption flagged as a one-line toggle if wrong. Engineers now review a working reference instead of interpreting a static frame.

Status

Where it stands

My World is live in development: the featured band, Reminders widget, and topic surfaces are implemented; the invitation prompt and mood taxonomy integration are in progress.

Reflection

What I'd want a hiring team to know

The takeaway I’d offer a hiring team is the shape of the work: I wrote the product doc engineers build from, the prompts that generate the content, the QA tooling that validates them, and increasingly the code itself.

At a pre-seed startup, the most valuable designer is the one who removes handoffs. That’s the designer I’ve become, and the design engineer I’m becoming.