Blog1 min readPremium

UX Patterns for AI Features That Don’t Feel Broken

UX Patterns for AI Features That Don't Feel Broken

I’ve used a lot of AI features over the last year that felt broken. Most of the time, the model was fine. The UI around it wasn’t.

A button that does nothing for six seconds. A spinner that never ends because the stream silently died. A half-written answer that disappears when you click away. A “Regenerate” that wipes out the answer you actually liked.

None of these are AI problems. They’re frontend problems, and they’re very fixable. Here are the patterns I reach for every time I build an AI feature.

Start with a state machine

Normal API calls have three states: loading, success, error. AI requests have more, and if you model them as a pile of booleans (isLoading, isStreaming, hasError, wasStopped), you will end up in impossible combinations like “loading and errored at the same time”.

State machine for an AI request: idle, submitting, streaming, complete, error, stopped

A discriminated union makes the impossible states unrepresentable:

type AiRequest =
  | { status: 'idle' }
  | { status: 'submitting'; startedAt: number }
  | { status:... premium content.
Premium

Keep reading with Premium

Get the rest of this guide plus every premium question, solution, and system design deep dive.

  • All premium solutions
  • System design deep dives
  • Company-specific prep

4.9/5 from our users