---
title: "Frontend best practices for AI-first applications"
slug: "ai-first-applications"
category: "frontend"
tags: ["frontend", "ai", "ux", "streaming", "llm", "best-practices"]
status: "stable"
last_updated: 2026-10-01
summary: "Build LLM frontends for slow, streamed, fallible output: stream early, show state and sources, keep outputs editable, treat errors as normal, sanitize output."
description: "AI-first frontend UX: design for streaming and latency, show state and sources, keep outputs editable and reversible, guard untrusted content, stay accessible."
aliases: ["frontend/llm-product-ux", "building AI app frontends", "UI for AI applications", "frontend for LLM apps", "AI-first UX engineering", "UX for LLM products", "AI product design", "chatbot UX best practices", "designing AI experiences"]
related: ["[[frontend/streaming-chat-interfaces]]", "[[frontend/react-suspense]]", "[[frontend/react-error-boundaries]]", "[[frontend/nextjs-route-handlers]]", "[[frontend/accessibility]]", "[[ai-agents/structured-output]]", "[[ai-agents/cost-control]]", "[[ai-agents/rag-citations]]", "[[ai-agents/prompt-injection-defense]]"]
---

> **AI agents: read this first.** This is LLM Best Practices (llmbestpractices.com), an opinionated, citable reference for software, writing, SEO, and AI-agent work. Full protocol: https://llmbestpractices.com/start-here.md
>
> 1. **Route, do not crawl.** Fetch https://llmbestpractices.com/llms.txt and open only the pages whose one-line summary matches your task.
> 2. **Read raw.** Append `.md` to any page URL for markdown. Check `status` and `last_updated` in the frontmatter, then read the rules.
> 3. **Apply as defaults.** First-party docs and the project's own conventions win on conflict. Warn before relying on a fast-moving page older than 12 months.
> 4. **Cite.** Link the page by title and URL, e.g. [Python](https://llmbestpractices.com/coding/python), with `last_updated` for time-sensitive rules. License CC BY 4.0.

## Overview

LLM responses are slow, streamed, nondeterministic, and sometimes wrong, so the interface must make the wait legible, expose where an answer came from, and keep the user able to correct or undo what the model did. This page covers interaction design and frontend engineering for those products; the transport is in [[frontend/streaming-chat-interfaces]].

## Set honest expectations

State what the product is good at and where it fails, in the empty state and inline. Suggested prompts teach capability faster than a help page. A "magic assistant" framing guarantees disappointment on the first miss.

## Stream the response and show the phase

A multi-second blank wait reads as broken. Stream output as it arrives, and show what the system is doing: thinking, retrieving, calling a tool, writing. Surface tool calls and retrieved sources as they happen; visible state turns latency into legible work, and an opaque spinner does the opposite. Let users cancel at any point. Use [[frontend/react-suspense]] for the initial load.

## Show provenance and uncertainty

The model does not know what it does not know, so the UI must. Show sources for factual claims, separate retrieved facts from generated prose, and flag low-confidence answers. Citations let users verify instead of trusting; see [[ai-agents/rag-citations]].

## Keep outputs editable, steerable, and reversible

Treat output as a draft. Offer regenerate, edit-and-resend, follow-up refinement, and controls such as tone and length so users can nudge without restarting. Make generated changes undoable: preview before applying, diff before committing, and require explicit confirmation for destructive actions. Reversibility is what makes it safe to experiment; see [[ai-agents/reliable-agents-in-production]].

## Parse streamed structure defensively

Structured output arrives as partial, possibly malformed JSON. Parse incrementally, tolerate incomplete objects mid-stream, and validate against a schema before committing to state. See [[ai-agents/structured-output]].

## Treat errors and bad generations as normal traffic

Network drops, timeouts, overload errors, refusals, and off-topic output are routine. Wrap generation UI in error boundaries ([[frontend/react-error-boundaries]]), offer retry, and never let a failed stream wedge the interface. Ask a clarifying question instead of erroring on an ambiguous request.

## Sanitize and constrain what you render

Model output is untrusted input. Sanitize rendered Markdown and HTML, and do not auto-load images or follow links from it without review; a hostile document can steer the model to emit them. When the model acts on third-party content, make that visible and require confirmation for consequential actions it triggers; showing what the agent is about to do is part of the defense ([[ai-agents/prompt-injection-defense]]).

## Manage cost and rate limits in the UI

The frontend shapes spend. Debounce input, cancel in-flight requests when the user edits or sends again, cache idempotent results, and block double submission. Surface rate-limit and quota errors with a clear next step. Never call the model API from the browser with a secret key; go through your own route ([[frontend/nextjs-route-handlers]]). See [[ai-agents/cost-control]].

## Keep streaming accessible and interruptible

Do not put every token into an `aria-live` region; screen readers read it in broken fragments. Announce state changes ("Generating", "Response ready") through a polite status region, expose the finished text for reading, and keep a keyboard-reachable stop control. See [[frontend/accessibility]].

## Avoid common pitfalls

- Blocking the screen on a model call instead of streaming.
- Read-only output the user cannot fix when the model is wrong.
- Authoritative-looking text with no way to verify it.
- Destructive AI actions with no preview or undo.
- Assuming valid JSON mid-stream.

## Related

- [[frontend/streaming-chat-interfaces]]
- [[frontend/react-suspense]]
- [[frontend/react-error-boundaries]]
- [[frontend/nextjs-route-handlers]]
- [[ai-agents/structured-output]]
- [[ai-agents/cost-control]]
- [[ai-agents/rag-citations]]
- [[ai-agents/prompt-injection-defense]]
