Lesson 8 of 8 · 58 min

AI in the UI + machine coding + capstone

Streaming AI UI patterns (protocols, batched tokens, conversation state, cancel/regenerate, citations, tool safety), machine-coding time-box strategy, and a self-scored FE system-design capstone mock with full rubric.

Lesson 8 · Capstone

AI in the UI + machine coding + mock

Engineering AI surfaces — not becoming an LLM course

AI-in-the-UI is table stakes for product FE: streaming tokens, cancel/regenerate, citation UX, conversation state as data, and INP under stream load. Then machine-coding patterns and a full self-scored system-design mock close the track.
Stay engineering: protocols, React rendering, state machines, accessibility of live regions, failure UX. Pattern language for prompts/agents can live in companion AI tracks — here you build the client system that makes them usable.

Streaming protocols

  1. 01fetch + ReadableStream — flexible; parse SSE or newline JSON yourself.
  2. 02SSE — natural for token streams; EventSource or fetch stream.
  3. 03WebSocket — bidirectional agent control, tool events, multiplex.
  4. 04Pick by: bidirectional need, infra, proxy support, backpressure story.
ts
1async function streamChat(body: unknown, onToken: (t: string) => void, signal: AbortSignal) {2	const res = await fetch('/api/chat', {3		method: 'POST',4		body: JSON.stringify(body),5		signal,6	})7	if (!res.ok || !res.body) throw new Error('stream failed')8	const reader = res.body.getReader()9	const dec = new TextDecoder()10	let buf = ''11	for (;;) {12		const { done, value } = await reader.read()13		if (done) break14		buf += dec.decode(value, { stream: true })15		// parse SSE lines / frames; onToken(piece)16		// keep parser robust to partial frames17	}18}

Conversation state as data

Model turns as an array of discriminated unions — not nested component state trees. Support regenerate-from-index, branch, edit-user-message-and-rerun, tool-call traces as first-class events. This is the same “state as data” discipline as L3 architecture applied to AI surfaces.
ts
1type Turn =2	| { id: string; role: 'user'; content: string }3	| { id: string; role: 'assistant'; content: string; status: 'streaming'|'done'|'error'|'cancelled'; citations?: Cite[] }4	| { id: string; role: 'tool'; name: string; input: unknown; output?: unknown; status: 'running'|'done'|'error' }56type Thread = {7	id: string8	turns: Turn[]9	// branch: parentId + alternative threads if you support forks10}

Agentic controls & provenance

  1. 01Cancel — AbortController; mark turn cancelled; keep partial text optional.
  2. 02Regenerate — truncate from assistant turn; resubmit with same user context.
  3. 03Edit & rerun — rewrite user turn; drop later turns or fork branch.
  4. 04Citations — inline markers + source list; links; hover previews; never invent hrefs.
  5. 05Tool trace panel — collapsible timeline for power users; hide by default on mobile.
  6. 06Tool safety — validate tool JSON with Zod; run tools server-side; allowlist actions; never treat model text as instructions for privileged ops.

Optimistic UX for variable latency

TTFT can be 200ms–10s+. Show pending skeleton or “thinking” with status from server events when available. Do not block the whole app. Keep composer usable for queueing or disable with clear reason while streaming if product requires single-flight.

INP and a11y on streams

  1. 01Batch token appends (rAF / every N chars) to avoid 1 React commit per token on huge replies.
  2. 02aria-live polite for completion — not each token.
  3. 03Focus management: do not steal focus every chunk; offer “jump to latest.”
  4. 04Reduced motion: less shimmer on thinking indicators.
  5. 05Virtualize long threads; streaming is a high-frequency input pipeline.
tsx
1function useBatchedText() {2	const [text, setText] = useState('')3	const buf = useRef('')4	const raf = useRef(0)5	const push = (chunk: string) => {6		buf.current += chunk7		if (!raf.current) {8			raf.current = requestAnimationFrame(() => {9				raf.current = 010				setText(t => t + buf.current)11				buf.current = ''12			})13		}14	}15	return { text, push, setText }16}

Machine-coding patterns (time-box strategy)

India/global loops and take-homes reuse a short list of builds. Structure beats perfection. Patterns: debounce vs throttle, virtualization, race-safe fetches, controlled vs uncontrolled forms, stable list keys.
  1. 01Autocomplete — debounce, abort, keyboard, a11y roles (you already designed it).
  2. 02Infinite list — cursor, observer, skeleton, error retry.
  3. 03Tabs / modal — roving tabindex / focus trap — show a11y fluency.
  4. 04Simple kanban — columns state, drag optional with keyboard alternative (2.5.7).
  5. 05Carousel — index state, buttons, aria-roledescription, reduced motion.
text
1MACHINE CODING 60–90m CLOCK20–8m   Clarify acceptance criteria + edge cases; write a mini checklist38–35m  Happy path vertical slice (renders + core interaction)435–55m Edge cases: empty, error, loading, keyboard555–70m Polish: a11y attributes, basic CSS, disable double submit670–90m Tests if required; narrate tradeoffs; clean dead code78Always: controlled state diagram in comments if stuck9Never: silent coding for 20 minutes without talking

Capstone mock — FE system design

Pick one: autocomplete · e-commerce PDP · notifications inbox. Run 45 minutes with RADIO. Self-score 1–5 on: requirements, architecture, NFRs, a11y, perf budget, failure modes. Target ≥4 on four of six before interviewing.
text
1CAPSTONE RUBRIC21. Requirements elicitation — written; signed off by “PM”32. System design — ADRs (rendering, state model, perf budget)43. Implementation — clean decomposition; tests at boundaries54. Observability — log + metric + trace wired65. A11y & perf audits — axe + Lighthouse + RUM plan76. Demo — 5-minute Loom that tells the *why* before the *what*89PDP sketch:10  SEO + LCP image; variant picker a11y; cart multi-tab BroadcastChannel;11  RSC shell + client add-to-cart; revalidate on price; CLS on gallery.12Inbox sketch:13  URL selection; infinite thread list; mark read optimistic; push via SSE;14  badge derived from cache; keyboard list navigation.15Autocomplete sketch:16  scale, cache, analytics privacy, a11y APG — you already know this.

Track synthesis — what you can claim

  1. 01Own a surface with eight production dimensions and a real definition of done.
  2. 02Pass React/Next batteries: re-renders, RSC boundaries, revalidate layers, hydration.
  3. 03Place state in four buckets; compose components without god files.
  4. 04Diagnose LCP/INP/CLS and pick rendering modes from constraints.
  5. 05Design a11y into widgets; steward DS tokens and gates.
  6. 06Drive FE system design for chat, dashboard, collab, feed, autocomplete (RADIO).
  7. 07Ship streaming AI UI without melting INP or accessibility.
Before your next loop: re-speak ten L2 questions cold, run one 45-minute FE system design on a prompt you have not rehearsed, and ship one small machine-coding kata with keyboard + empty/error states under a timer.

AI UI — failure modes and senior signals

  1. 01Parser fragility — partial SSE frames crash JSON.parse. Buffer lines; tolerate incomplete fences.
  2. 02Per-token setState — main-thread thrash. Batch with rAF.
  3. 03Live region spam — SR unusable. Announce completion only.
  4. 04No cancel — runaway cost and stuck pending UI. AbortController + cancelled status.
  5. 05Tool output as HTML — XSS. Treat as data; render structured UI from validated JSON.
  6. 06Prompt injection via tool results — never elevate model text to privileged instructions; allowlist server-side tools.
  1. 01Q: SSE vs WebSocket for chat tokens? SSE (or fetch streams) fits unidirectional token streams with simple infra and automatic reconnect stories. WebSocket wins when you need multiplexed bidirectional control (cancel, tool events, collaborative agent state) on one connection. Many products start with fetch streams and add WS only when control plane needs grow.
  2. 02Q: How do you model regenerate and branch? Turns are data. Regenerate truncates or forks from an assistant index and starts a new streaming turn. Branch keeps alternate threads keyed by parentId. Component-local strings cannot represent this without pain. Discriminated unions make tool traces and citations first-class.
  3. 03Q: What is the machine-coding clock for a senior? Clarify acceptance criteria first (8m), vertical slice happy path (to ~35m), then empty/error/loading/keyboard (to ~55m), then polish and tests. Narrate continuously. Keyboard and disabled double-submit beat pixel-perfect CSS in the last ten minutes.
  4. 04Q: Capstone self-score rule of thumb? If architecture is a 5 but NFRs were never named, ownership score collapses. Unprompted perf budget, a11y path, and failure modes are the L1 bar this track trained. Re-run the mock until four of six dimensions are ≥4.
Wire AI surfaces into the same eight ownership dimensions from L1: rendering (stream vs block), state (turns as data), data contracts (tool schemas), performance (batched paints), a11y (live regions), design system (message bubbles, code blocks), observability (TTFT, error rate, cancel rate), release (flag the new composer).
text
1// Capstone week plan (solo)2// Day 1: RADIO writeup + state model + acceptance criteria3// Day 2: vertical slice streaming UI + cancel4// Day 3: citations/tool panel + a11y pass5// Day 4: machine-coding kata under timer (autocomplete or modal)6// Day 5: 45m system-design mock on unseen prompt; score rubric; gap list78// Metrics to log on AI UI9// ttft_ms, tokens_per_sec_client, cancel_rate, parse_error_rate, inp_composer

Capstone assembly — AI UI + machine coding + mock

Treat the AI composer as a product surface with the L1 eight dimensions. Rendering: stream tokens with batched paints. State: turns as discriminated unions. Data: tool schemas validated server-side. Perf: rAF batching + virtualize thread. A11y: polite completion announces, no focus steal per chunk. DS: shared MessageBubble, CodeBlock, CitationChip. Observability: TTFT, parse errors, cancel rate, composer INP. Release: feature flag new streaming client.
Machine-coding day-before checklist: re-implement autocomplete and a modal from memory under 45 minutes; speak the APG requirements while coding; ship empty/error/loading; disable double submit; leave a comment with complexity and tradeoffs. Prefer getByRole-shaped markup even if you do not write tests in the round.
System-design mock day-before: pick a prompt you have not rehearsed (photo viewer, PDP, inbox). Run full RADIO on a timer. Record yourself. Score six axes 1–5. Anything under 4 becomes tomorrow’s drill. This closes the track the same way senior candidates actually prepare — deliberate practice with a rubric, not passive reading.
  1. 01AI UI week-1 — fetch stream parser, cancel, batched text, turn list UI.
  2. 02AI UI week-2 — regenerate/edit, citations, tool trace panel, a11y pass.
  3. 03Kata rotation — autocomplete · infinite list · tabs/modal · carousel.
  4. 04Mock rotation — chat · feed · collab · PDP · inbox.
  5. 05Pass bar — ≥4/5 on four of six capstone axes + cold L2 battery sample.
ts
1// Minimal turn reducer sketch2type Action =3	| { type: 'user_send'; id: string; content: string }4	| { type: 'assistant_start'; id: string }5	| { type: 'assistant_token'; id: string; chunk: string }6	| { type: 'assistant_done'; id: string }7	| { type: 'cancel'; id: string }8	| { type: 'regenerate'; fromIndex: number }910// regenerate: slice turns to fromIndex; dispatch assistant_start
Final track close checklist: (1) cold answer ten L2 questions with mechanism + production risk + proof, (2) bucket state on three real screens at work, (3) diagnose one LCP and one INP from a real trace, (4) implement combobox keyboard against APG in under an hour, (5) run one chat or feed RADIO mock timed, (6) ship a tiny streaming UI with cancel + batched paints, (7) re-score the capstone rubric. When all seven are green, you are interview-ready for product FE craft rounds — not because you memorised frameworks, but because you own surfaces.
Tool-calling UI note: render tool rows as structured cards from validated JSON (name, args summary, status, result summary), not as raw model prose the user must parse. Hide secrets. Allow cancel of long tools. If the model invents a tool name outside the allowlist, show an error state — never execute client-side privileged actions from free text.
docsMDN — Streams APIMDNdocsReact — useTransitionreact.devdocsVercel AI SDK — Streaming (conceptual patterns)VerceldocsReact — Server Componentsreact.devarticleGreatFrontEnd — 50 React coding questionsGreatFrontEnd

Checkpoint

Best reason to batch token updates with requestAnimationFrame while streaming?

ASSE forbids more than 60 events/sec.BPer-token React commits create main-thread thrash and hurt INP; batching coalesces paints.CIt makes the model respond faster.
Sign up free to answer and see why

Checkpoint

How should conversation regenerate be modeled?

AOverwrite a string in a random component ref.BTreat turns as data: truncate/fork from an index and start a new assistant turn with status streaming.CReload the page.
Sign up free to answer and see why

Checkpoint

Machine-coding: 10 minutes left, happy path works, no keyboard support on a custom listbox. What do you do?

AStart a CSS rewrite for visual polish only.BAdd arrow/enter/escape handlers + aria roles from APG; narrate remaining gaps.CExplain that a11y is a nice-to-have after GA.
Sign up free to answer and see why

Checkpoint

E-comm PDP multi-tab cart: user adds item in tab A; tab B still shows empty. Strong FE fix?

ATell users not to open two tabs.BBroadcastChannel or storage events to sync cart cache; server remains source of truth on conflict.CPut cart only in a module-level variable.
Sign up free to answer and see why

Checkpoint

Capstone self-score: strong architecture, no NFRs named. What happens on the senior rubric?

AStill hire — architecture is enough.BScore drops on ownership — add perf budget, a11y, and failure modes before finishing.CNFRs only matter for backend designs.
Sign up free to answer and see why

Ready to run a 45-minute FE system design mock and a streaming AI UI deep dive without notes?

New to itGetting thereConfident

Takeaways

  • AI UI: stream parsers, batched paints, cancel/regenerate, citations, turns as data.
  • Protect INP and a11y under streaming load — no per-token announce spam.
  • Machine coding: clarify, vertical slice, edges, keyboard, narrate.
  • Capstone: requirements · architecture · NFRs · a11y · perf · failures.
  • You now have the product FE craft loop — schedule real mocks and re-score.

Track complete. Revisit L2 Qs weekly and run one FE system-design mock before each loop.

Sources

Free to read · better with Enzo

Learn it with Enzo

Save your progress, answer the checkpoints, and let Enzo quiz you on what you just read.