Two Voices: building a design system for an AI app

Week three of building Doch

21 Oct 2026

Doch now has a design system of its own. I called it Two Voices. Most of the work came down to one question chat UIs don’t usually have to answer: when an AI speaks for you, does it get your colour or its own?

A Doch call has three participants but only two on the line: the business, speaking German, and Doch, speaking for you. You’re watching from your phone, usually without following the German. So the screen has to tell you who’s speaking at a glance, without making you read a label.

When an AI speaks for you, is it you?

My first answer was yes. Doch speaks on your behalf, so I mapped coral to you and to Doch on the call, and teal to the business.

That mapping fell apart in the briefing. There, you and Doch are talking to each other, so you can’t share a colour. Doch ended up white in the briefing and coral on the call. Same agent, two visual identities, and it read like two different agents.

The agent gets its own colour

So I rewrote it as one rule with no exceptions: three participants, two colours. Teal is always the business. Coral is always Doch, on every screen. You’re neutral, and your own messages render white.

For an agent this matters more than in a normal chat UI. You’re not just reading replies. You’re supervising Doch while it talks to someone else for you, so you need to tell its words apart from yours at a glance. Most AI chat apps already keep the user’s side quiet and give the assistant the identity. Doch goes one step further.

During a call, the screen glows in the colour of whoever is talking.

Testing the palette

Before committing to a palette, I set up three token sets on the same three screens: a live call, the moment Doch needs you (“They can offer Thu 29 Oct at 10:00. Book it?”) and the list of calls. Same components, same content. Only the token values changed.

Looking back, my first round wasn’t a fair test. Only one set gave each speaker their own colour, and that’s standard in any chat UI. So I reran it with a speaker pair in every set. Once all three could tell the speakers apart, the real question was which pair.

Three phones showing the same live call to a property manager in three token sets, each with a colour per speaker: Warm sand in terracotta and olive, Open air in coral and teal, and Head office in blue and ochre.

Same screens and content, with a colour per speaker in every set: Warm sand, Open air and Head office.

I went with teal and coral, for four reasons:

  • Warm sand’s pair broke for colour blindness. Terracotta and olive are a red-green pair. In a colour blindness simulation they nearly merge, which affects roughly 1 in 20 people.

  • Head office felt like the institutions you’re calling. It separated the speakers best, but it reads like a bank or the Bürgeramt. Doch exists because those calls are stressful, so the app shouldn’t feel like one of them.

  • Warm for your side, cool for theirs. Coral is Doch, on your team. Teal stays with the other side of the call.

  • The glows stay clean. Teal and coral are opposites, so where the two glows meet at the top of the call screen, they fade into off-white instead of mixing into brown.

A table comparing the colour difference between the two speaker colours in three token sets. Warm sand scores 53 for normal vision but 11 and 7 for red-green colour blindness. Open air scores 89, 65 and 44. Head office scores 102, 104 and 96.

How far apart each speaker pair stays for normal vision and the two common types of red-green colour blindness. Warm sand’s pair nearly merges.

A colour wheel with coral for Doch at the top and petrol teal for whoever picks up at the bottom, 180 degrees apart.

Where the palette landed: coral #EC6E55 for Doch and petrol teal #2790A5 for whoever picks up, 180° apart.

Where I pushed back on Claude

Claude’s first pass was darker and muddier: #12636B for teal and #A3461F for a rusty coral. I pushed back. I wanted them brighter, and real opposites on the colour wheel. They landed on petrol teal #2790A5 and coral #EC6E55, 180° apart.

Claude also went for a tight corner radius. I bumped up the radius tokens so the app feels softer, closer to a friend helping you than to the offices you’re calling.

The glow was my call too. During a call, the background takes a low-opacity wash of whoever is speaking: teal for the other side, coral for Doch. You know who’s talking before you’ve read a word.

Tokens made the rule cheap to change

Each colour became a ten-step primitive scale, teal-50 to teal-900 and coral-50 to coral-900. Components never reference the primitives directly. They point at semantic tokens named by role, like the business’s bubble, Doch’s bubble and the text on top of them. So when Doch stopped sharing your colour, I re-pointed a handful of semantic tokens instead of touching every component that used them.

The two colour scales in Two Voices, teal-50 to teal-900 and coral-50 to coral-900, with hex values. Teal-500 and coral-400 are the base voice colours.

The two scales: petrol teal for whoever picks up, coral for Doch. Teal-500 and coral-400 are the voice colours, 180° apart.

The rest of the foundation is warm and light: a sand-coloured canvas, Figtree for text, Bricolage Grotesque for headings, and a glass tab bar with New call in it rather than a floating button. I wanted it welcoming, not technical, so there's no black on the main button or the badges.

Building a design system for an AI app in one morning

I built Two Voices in one morning with Claude. The scope was tight: apply colour, type, spacing and corner radius to the components Doch already had, and add no new ones. Design tokens first, then the components that use them, then the code, where the tokens live as CSS custom properties in one stylesheet.

A few decisions from the system:

  • Coral for the main action. "Book it" and "Call" are solid coral. Secondary actions stay quieter.

  • Badges are never tappable: Needs you, Live, In their queue, Failed. Each badge takes its tone from its label, so a new status can’t end up the wrong colour.

  • Errors that look like errors. The error red is #C8102E, with an alert icon, a red label and a red bar down the side of the field. It holds about 5:1 or better on the app’s main backgrounds.

Doch's Needs you sheet asking whether to book a Thursday slot, with a dotted badge, the reason it is asking and a countdown

The Needs you sheet in Two Voices: a badge with a dot, the reason Doch is asking, and what they actually said.

The logo is the conversation

The logo is two overlapping circles: teal for the business, coral for Doch, next to the "Doch" wordmark in dark teal. I tried a few directions and chose a symbol with a wordmark, because the symbol works on its own as the app icon.

The overlap took longest. A blend turned the middle a muddy brown that shifted with the background. The final version is flat circles, with the overlap drawn as its own shape in teal-800. I checked it at 240, 32 and 16 pixels on sand and black. At favicon size teal-800 still reads as teal, where teal-900 looked like a hole. The overlap is the conversation, and it happens on the business's side, in German, so it takes their colour.

Three Doch logo directions in teal: two rings inside the o, a symbol of two overlapping circles with a wordmark, and a plain wordmark

Three logo directions. B, the symbol and wordmark, won because the symbol works on its own as the app icon.

What came next

With the system in place, the next posts are about real calls to real businesses, and what happened in the first few seconds of them.

Akber Ahmed is a senior product designer in Berlin, designing and building AI products. See more of his work at akberahmed.com/projects.

Doch build log
01Designing AI agents: what they say no toWeek one · 7 Oct02AI voice agent prototype to working app in a weekWeek two · 14 Oct
03Two Voices: a design system for an AI appWeek three · 21 OctYou're hereYou're here
04I made 35 phone calls in German. Four people stayed on the line.Week four · 30 Oct