Engineering

Build Your First AI-Backed UI (Without Overcomplicating It)

A bare-bones CSS generator that shows the pattern: a normal form in front, a constrained system prompt and API route behind — enough to ship your first AI feature.

View reference repoOpen live demo

If you have never shipped an AI feature, the jump from “chat with a model” to “product UI that uses a model” can feel opaque. It does not have to be. Most useful AI products are not chatbots — they are ordinary interfaces with one carefully scoped call to a model behind the scenes.

Our open example, AI CSS Generator, is intentionally bare-bones. You describe styles in plain language; the app returns CSS properties, previews them on a box, and lets you copy the result. The value for developers is the wiring: how the form talks to an API route, how the prompt is locked to one job, and how failures surface in the UI. Source: dreamerkumar/ai-css-styles-generator.

The mental model

Front: a normal UI (textarea, button, preview, errors). Back: a server route that holds the API key, a tight system prompt, and a single model call. Users never see the provider console — they see your product.

Why Start With a Narrow Task

Chat is open-ended. Product features should not be. The CSS generator only answers one question: “Which CSS properties match this description?” That constraint is a feature. It keeps outputs parseable, previews reliable, and costs predictable. When you build your first AI-backed screen, pick a similarly narrow job:

  • Turn a sentence into three subject lines
  • Suggest alt text for an uploaded image
  • Normalize a messy address into fields
  • Propose CSS for a preview box (this demo)

Narrow tasks are easier to prompt, validate, and ship. You can always widen later.

Step 1 — Build the Interface First

Ignore the model until the UX works with fake data. In this project the UI is a prompt box, add-vs-replace mode, a generate button with loading state, error display, CSS textarea, validate/preview, and copy. That is ordinary React — hooks for state, fetch when the user clicks Generate.

const res = await fetch("/api/get-css-style-for-a-box-from-ai-prompt", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ prompt }),
});
const data = await res.json();
// Treat data.response as CSS — or as a known "Invalid request" string

The hook also handles empty responses and network errors so the button can show a spinner and the page can show a clear message. That layer matters more than the model brand: users forgive a weak suggestion; they do not forgive a silent hang.

Step 2 — Put the Model Behind an API Route

Never call the provider from the browser with your secret key. The demo uses a Next.js API route that reads the prompt from the POST body, calls Anthropic Claude, and returns JSON. The key stays in the environment (ANTHROPIC_API_KEY / server-only config). That is the same pattern you will use with OpenAI, Gemini, or any other vendor.

Minimum server responsibilities

  • Reject non-POST / missing prompt early
  • Hold credentials server-side only
  • Pass a system prompt + user message to the model
  • Return a small JSON payload the UI already understands
  • Map provider failures to a 500 the client can display

Step 3 — Restrict the Prompt to the Task

This is the “nitty-gritty” that makes the demo teachable. The system prompt does not say “be a helpful assistant.” It defines a contract:

You are a CSS code generator. Your task is to convert the user's
request into valid CSS properties, returning them exclusively as
'key: value;' pairs—one property per line.
Do not include any other text, HTML, explanations, or classes...

If the user's request is not clear, return:
"Invalid request: It's not clear..."

That does three important things for a first-time builder:

  1. Shape — the UI can treat success as CSS lines, not free-form prose.
  2. Refusal path — unclear prompts return a known error string the client already checks for (Invalid request).
  3. Safety of scope — the model is less likely to wander into tutorials, markdown fences, or unrelated answers that break the preview pipeline.

Constrained prompt

  • Named role + single output format
  • Explicit “do not” list (no HTML, no commentary)
  • Documented failure message the UI can branch on

Open chat prompt

  • “Help the user with CSS however you can”
  • Answers wrapped in markdown or explanations
  • UI has to scrape or guess where the CSS is

Step 4 — Close the Loop in the Product

Generated CSS is not the end. The demo appends or replaces styles in a textarea, validates, and previews on a box. That loop — generate → inspect → fix → copy — is what makes AI feel like a tool instead of a slot machine. When you design your first feature, decide what “done” looks like in the UI before you tune temperature or models.

API keys vs chat subscriptions

Provider chat apps and API consoles are different billing surfaces. This project needs an Anthropic Console API key with credits — a Claude chat subscription alone does not fund server calls. Plan for that when you onboard teammates.

A Checklist for Your First AI Feature

Ship something small this week

  • Pick one structured output (JSON fields, CSS lines, a short list)
  • Sketch the UI with a mocked response
  • Add a server route; move the secret off the client
  • Write a system prompt that names format + failure text
  • Validate or preview before you trust the result
  • Show loading and error states like any other network call

Try the Example, Then Steal the Shape

Open the live AI CSS Generator, generate a few styles, then clone the repo and read the API route beside the React hook. You do not need a platform team or an agent framework to start. You need a clear user job, a constrained prompt, and a boring HTTP boundary between your UI and the model.

git clone https://github.com/dreamerkumar/ai-css-styles-generator.git
cd ai-css-styles-generator
npm install
# add ANTHROPIC_API_KEY to .env.local
npm run dev

Once that pattern clicks, the next feature — whatever your product needs — is the same three layers with a different contract. That is how you go from “I use AI in chat” to “I ship AI behind my own interface.”