cf.completefrontend
My progress
FUNDAMENTALS · MODULE 1

Component questions vs app questions

Frontend design prompts come in two shapes, a reusable component or a whole product, and each needs a different emphasis and a different use of your 45 minutes.

Two prompts, one wrong answer

Picture two candidates on the same afternoon. The first gets "Design an autocomplete for a search box." The second gets "Design a news feed like the one on a social network." Both have studied the same notes, and both open with the same plan: a box for the browser, a box for the API server, a box for the database, a CDN in front.

The first candidate spends twelve minutes drawing servers for a widget that has one endpoint. The interviewer keeps asking "what does the parent page pass in?" and "what happens when I press the down arrow?" The candidate never reaches keyboard support, never names the combobox role, and never handles the race between two slow responses. The feedback says: "Strong backend instincts, didn't design the component."

The second candidate does the opposite mistake. They write a careful PostCard props type, discuss whether onLike should be a callback or an event, and debate slots for the footer. Thirty minutes in, they haven't said how the feed loads its second page, where posts are cached, or how a new post shows up. The feedback says: "Good React knowledge, no system design."

Two panels side by side. Left: the prompt Design an autocomplete. The candidate drew an API server, a database, and a CDN, all marked as wasted. The rubric asked for a keyboard map, the combobox role, and handling stale responses, all left blank. Right: the prompt Design a news feed. The candidate drew a PostCard props type, marked as wasted. The rubric asked for cursor pagination, a client cache, and how new posts arrive, all left blank.Design an autocompletewhat they drewAPIDBCDNwhat the rubric asked forkeyboard mapcombobox rolestale responsesDesign a news feedwhat they drewPostCard propswhat the rubric asked forcursor paginationclient cachenew posts arriveright effort, wrong shape: the scored lines stay blank
Each candidate gave the other prompt's answer. The work was fine; it just landed on lines the rubric didn't have, while the lines it did have stayed empty.

Why the shape of the prompt matters

Frontend system design prompts come in two main shapes. A component question asks for one reusable piece of UI that other engineers drop into their pages. An app question asks for a whole product with screens, a server, and data that changes while people use it. Each shape has a different main user, a different hard part, and a different place where your minutes should go.

The interviewer usually knows which shape they asked for, and their rubric reflects it. A rubric for a date picker has lines like "keyboard navigation", "controlled vs uncontrolled", and "locale and time zones". A rubric for a chat app has lines like "message ordering", "real-time transport", and "offline send queue". You score on the lines that exist.

Time spent on topics that aren't on the rubric is time you can't spend on the ones that are.

This lesson teaches you to spot the shape in the first minute, what to emphasize in each, how the RADIO time split moves with scope, and how to handle the prompts that sit in between. It builds on the RADIO framework lesson (Requirements, Architecture, Data model, Interface, Optimizations) and on What interviewers look for, by level. Read those first if the five steps are new to you.

The mental model: who is your user, and where is the hard part?

Think of a door handle and a house. An architect asked to design a door handle thinks about hands: the grip, how far it turns, whether a child or someone with arthritis can use it, and whether it fits doors made by other companies. An architect asked to design a house thinks about rooms, pipes, wiring, and how people move between spaces. The handle is one line in a long list.

Both are design, and both architects are skilled. But the questions they ask, the drawings they make, and where their hours go are completely different. Frontend prompts work the same way.

The two archetypes

A component question asks for one piece of UI with a public API: an autocomplete, an image carousel, a date picker, a data table, a modal dialog, a toast system. You are writing a small library, and the server is one endpoint or none at all.

Your first user is another developer, who passes in props and listens for events. Your second user is the person who clicks, types, or listens with a screen reader.

An app question asks for a product: a news feed, a chat app, an online store, a photo sharing site, an email client. You are the tech lead. Your user is the customer, on a slow phone, scrolling for twenty minutes. The hard parts are about data: where it comes from, how it's cached, how it stays fresh, and how the first page loads fast.

Between them sit feature questions: a comment section, a notification bell, a checkout flow, a file uploader with progress. They are a small app inside a bigger one. They need some API design and data flow, plus a component-style contract with the page that hosts them.

A spectrum of prompts in three groups from left to right. Component: tooltip, modal dialog, autocomplete, data table. Feature: comment section, notifications, file uploader. App: news feed, chat app, docs editor. An axis below runs from left to right. On the left, the main user is a developer and the hard part lives inside the box. On the right, the main user is a customer and the hard part lives between client and server.ComponentTooltipModal dialogAutocompleteData tableFeatureComment sectionNotificationsFile uploaderAppNews feedChat appDocs editoruser: a developeruser: a customerhard part: inside the boxhard part: client to server
Prompts sit on a line, not in two boxes. The further right, the more of the answer is about data moving between the browser and servers; the further left, the more it's about one rectangle's API and behavior.

Two tests that sort almost any prompt

You don't need a long checklist. Two questions sort almost every prompt you'll get.

  1. Who is the main user of my design? If it's a developer who will import it, you're designing a component. If it's a customer using a product, you're designing an app.
  2. Where does the hard part live? If it lives inside one rectangle on the screen (keyboard, focus, rendering, timing), it's a component. If it lives between the browser and the server (loading, caching, syncing, scale), it's an app.

When both answers point the same way, you're done. When they disagree, you have a feature question or an ambiguous prompt, and you should ask (chapter 3 covers how).

QuestionComponent questionApp question
Main userA developer who imports it, then the person who uses itThe customer using the product
Where the hard part livesInside the rectangle: input, focus, rendering, timingBetween client and server: loading, caching, freshness
What the interface meansProps, events, slots, keyboard mapEndpoints, payloads, pagination, real-time messages
How many boxes in the architecture3 to 5, all inside the browser8 to 12, across browser, edge, and servers
What success looks likeAnother team uses it without reading the sourceFast first page, fresh data, survives bad networks
Typical deep divesAccessibility, request races, virtualization, positioningPagination, normalized cache, real-time, rendering strategy

Check your understanding · Exercise 1

Which of these prompts are component questions? Select all that apply.

Spotting the shape in the first minute

Most prompts tell you their shape in the words they use. You only need to listen for it, then confirm with one question. This takes under a minute and decides how you spend the next forty.

Signal words in the prompt

  • Component signals: "component", "widget", "for our design system", "reusable", "that other teams can use", "embeddable", or a noun that is clearly one piece of UI ("a date picker", "a modal", "a carousel").
  • App signals: a product name ("Design Twitter", "Design YouTube"), "app", "platform", "site", "for millions of users", or a verb about people doing things ("users can post, follow, and comment").
  • Feature signals: "a section of", "a page in", "add X to our product" ("add comments to our blog", "a checkout flow for our store").

Watch for prompts that name a product but ask for a part of it. "Design YouTube" is an app. "Design YouTube's video player" is a component, with a hard part (adaptive streaming, buffering states, captions, keyboard shortcuts) that lives inside one rectangle.

A decision tree. The first question: who is the main user? If a developer, ask where the hard part lives: inside the box means a component question, focused on the API and accessibility; between client and server means a feature, so ask first. If a customer, ask the same: inside the box means a feature, so ask first; between client and server means an app question, focused on data and scale. At the bottom, a note: then confirm the shape in one sentence and offer your default.Main user?developercustomerHard part lives?Hard part lives?inside boxto serverinside boxto serverComponentAPI, a11yFeatureask firstFeatureask firstAppdata, scalethen confirm the shape in one sentence,and offer your default
When both tests agree, the shape is clear. When they disagree, you are probably looking at a feature or an ambiguous prompt: ask one question and offer a default.

Questions that confirm the shape

Even when the words are clear, confirm in one sentence. It costs ten seconds and shows the interviewer you know the two shapes need different answers. Good confirming questions sound like this:

  • "Is this a shared component for a design system, used by many teams, or a field in one form?" (for a date picker)
  • "Should I treat this as a reusable editor component with a clean API, or as a product where documents are saved and shared?" (for a rich text editor)
  • "Do you want the whole product, or should I focus on the feed page and treat profiles and messaging as out of scope?" (for Design Instagram)

Notice that each question offers a default. Interviewers often say "your call", and a candidate who picks a sensible scope and explains why scores better than one who waits for permission.

Prompts that could be either

Some prompts are open on purpose, to see whether you notice. The common ones, and a sensible default for each:

PromptAs a componentAs an appSensible default
Rich text editorEditor with toolbar, selection model, paste handling, pluginsDocs product with saving, sharing, and live editingComponent, with one short section on saving
Image galleryGrid and lightbox with keyboard, lazy loading, zoomPhoto site with uploads, albums, and sharingAsk: the two answers barely overlap
Data tableSorting, filtering, virtualized rows, sticky headersAn admin dashboard with server-side queries and exportsComponent; mention server-side sorting at scale
Video playerControls, buffering, captions, adaptive bitrateA video platform with uploads, feeds, commentsComponent, unless the prompt names a product
Poll widget for news sitesEmbed snippet, isolation, tiny bundle, accessibilityPoll service with vote limits and live resultsComponent with a small API: get poll, vote, results

Think first

The prompt is "Design a poll widget that news sites can embed in their articles." Component or app, and where would most of your time go?

Check your understanding · Exercise 2

You're given "Design a rich text editor." Which first moves are good? Select all that apply.

Component questions: think like a library author

In a component question, the interface is the product. The server is small, so the design lives in three places: the API another developer types, the behavior the end user feels, and how the component fits into pages you've never seen.

An autocomplete component in the middle, drawn as a box with an input, a popup list, and a controller that owns timing, keys, and a cache; its state includes query and activeIndex. On the left, a developer sends props in and gets events out. On the right, an end user sends keys and taps in and gets announcements back. Two notes below: the developer asks whether the API is clear, small, and typed; the end user asks whether they can use it with keys or a screen reader.developerend userAutocompleteInputPopup listControllertiming, keys, cachequery, activeIndexprops inevents outkeys, tapsannounceddeveloper: is the APIclear, small, typed?end user: can I use itwith keys or a reader?
A component question has two users, and both are graded. The left side is the Interface step: props and events. The right side is most of the deep dives: keyboard, focus, and what a screen reader hears.

Props and events: the contract

Start the Interface step by writing the props as a type. Each prop is a decision you can defend in one sentence. What goes in (items, value, label), what comes out (onChange, onSelect, onOpenChange), and which defaults make the common case one line of code.

ts
type AutocompleteProps<T> = {
  // Parent owns the network call; the component owns timing and keyboard.
  search: (query: string, signal: AbortSignal) => Promise<T[]>;
  getLabel: (item: T) => string;
  renderOption?: (item: T, state: { active: boolean }) => ReactNode;
  value?: T | null;          // controlled when given
  defaultValue?: T | null;   // uncontrolled otherwise
  onChange?: (item: T | null) => void;
  minChars?: number;         // default 2
  debounceMs?: number;       // default 200
  label: string;             // required: the accessible name
};
A component's interface is a type. Passing an AbortSignal lets the component cancel stale requests, and making label required means no team can ship it without an accessible name.

Controlled or uncontrolled is the first question every interviewer asks about state. Controlled means the parent owns the value and passes it in with value and onChange, like a React input with value. Uncontrolled means the component keeps its own value and the parent only reads it when needed, with defaultValue. Good shared components support both: controlled for forms that validate on every change, uncontrolled for the quick case.

A common mistake is to emit vague events. onChange(value) for a modal that can close five ways is not enough. Say why it closed: onOpenChange(false, { reason: "escape" }) lets a form warn about unsaved changes only when the user pressed Escape, not when they clicked Save.

Customization without forks

Every team that adopts your component will want it to look slightly different. If the only way to change the option row is to copy your code, you'll have twelve forks within a year. Pick how teams customize it, and say why.

Decision How should other teams customize the look of the component?

Configuration props

Flags and values: size, variant, showAvatar, maxVisible.

Pros

  • Easy to learn and document.
  • The design system keeps full control of the markup.

Cons

  • Grows a new prop for every request.
  • Can't express layouts you didn't foresee.

Slots or render props

Pass a function or element for a part: renderOption, renderEmpty, a footer slot.

Pros

  • Teams change one part without rewriting the rest.
  • The component still owns keyboard, focus, and ARIA.

Cons

  • Custom markup can break accessibility if it adds its own focusable elements.
  • More API surface to test.

Headless hook

Ship the behavior only: useCombobox() returns state and prop getters; the team renders all markup.

Pros

  • Total freedom of markup and styling.
  • Behavior and accessibility logic stay shared.

Cons

  • Every team must wire the prop getters correctly.
  • More work for the simple case.

What we pick: For a design-system component, combine the first two: a few configuration props for the common cases and slots for the parts teams most often change. Offer a headless hook as a second layer only if many teams need fully custom markup. Good examples to name: Downshift and React Aria ship headless hooks, and Radix ships unstyled parts that teams style themselves.

States and accessibility

List every state the component can be in and give each a design: idle, loading, results, empty, error, disabled, and the awkward ones like very long text or 10,000 items. Interviewers notice when a candidate draws only the happy path.

Accessibility is almost always one of your deep dives. Name the pattern from the WAI-ARIA Authoring Practices Guide (APG): combobox with a listbox for an autocomplete, dialog for a modal, tablist for tabs. Then name the keyboard map (arrows, Enter, Escape, Home, End, Tab), where focus goes, and what a screen reader announces, for example through aria-activedescendant and a polite live region for the result count. The ARIA widget patterns lesson covers each pattern in depth.

Fitting any page

  • Performance inside the box: debounce typing, virtualize long lists, lazy-load hidden slides, avoid layout shift when the popup opens.
  • Theming: CSS custom properties or design tokens, so teams change colors without overriding your selectors.
  • Layout edges: popups that flip near the viewport edge, right-to-left languages, phone keyboards that cover half the screen.
  • Rendering: works with server rendering (no window access during render) and doesn't break hydration.
  • Bundle size: a shared component ships on many pages, so 20 KB of extra JavaScript is paid by every one of them.

Check your understanding · Exercise 3

You're designing a modal dialog for a design system. Which choices make its API better? Select all that apply.

App questions: think like a tech lead

In an app question, the hard parts live between the client and the server. Props still exist, but nobody will grade the props of your PostCard. The challenge is breadth: more parts, more data, more ways to fail. You won't cover everything, so the skill is picking what matters and showing how it fits together.

The architecture of a news feed app. In the browser, three stacked layers: views and routes, which are pages split by route; the client store, holding normalized posts and users; and the data layer, which fetches, retries, and tracks cursors. Data flows up from the data layer to the store to the views. On the right, the edge has a CDN for images, JavaScript, and HTML, which the views load from. The servers have the feed API, answering GET /feed with a cursor, and a push channel sending new-post notices by server-sent events. The data layer calls the feed API, and the push channel sends notices to the data layer.BrowserViews and routespages, code splitClient storenormalized posts, usersData layerfetch, retry, cursorsEdgeCDNimages, JS, HTMLServersFeed APIGET /feed?cursorPush channelSSE: new posts
In an app question, the interesting lines are the arrows between boxes. Each one becomes a question: how pages load, how the store stays fresh, what happens when a call fails.

The client-server contract

In an app question, the Interface step is mostly the network API. Name the two or three calls the main screen needs, with their payload shape, how they page, and how errors come back. You don't need every field; you need the fields that drive decisions.

http
GET /api/feed?cursor=eyJpZCI6OTg3fQ&limit=20

200 OK
{
  "items": [
    { "id": "p_981", "authorId": "u_12", "text": "...",
      "media": [{ "url": "...", "width": 1080, "height": 1350 }],
      "likeCount": 42, "likedByMe": false, "createdAt": "2026-10-19T09:12:00Z" }
  ],
  "users": { "u_12": { "name": "Asha", "avatarUrl": "..." } },
  "nextCursor": "eyJpZCI6OTYxfQ"
}
Three choices are visible in one response: a cursor instead of an offset, so new posts don't shift pages; image width and height, so the layout reserves space before the image loads; and authors sent once in a side map, so the client can store each user once.

Say why you picked REST, GraphQL, or a backend-for-frontend (a thin server shaped for one client). For a feed, a single REST endpoint with a cursor is a fine default. GraphQL earns its place when many screens need different slices of the same data. The interviewer cares that you chose on purpose, not which one you chose.

Data flow and the client store

Next, say where server data lives on the client and how it moves. The usual answer is a query cache (TanStack Query, SWR, or RTK Query) keyed by request.

For data that appears on many screens, add normalization: each post and user stored once by id, and lists holding only ids. Then a like on a post in the feed also updates the same post on the profile page, because there is only one copy. Apollo Client and Relay normalize automatically for GraphQL; with TanStack Query or SWR you add a small merge step or a separate entity store.

Separate the kinds of state out loud: server state (posts, users), UI state (which menu is open), URL state (the current tab, a search query, a selected post), and form state (a half-written comment). Each lives in a different place, and saying so shows you know why.

Freshness, loading, and failure

  • Freshness: how new content arrives. Polling (typically every 30 to 60 seconds), server-sent events, or WebSockets, and why. Most feeds show a "New posts" pill instead of pushing content under the reader's thumb.
  • The user's own actions: optimistic updates for likes and comments, with rollback when the server says no.
  • First load: server rendering or streaming for the first page, code splitting by route, images sized and lazy-loaded, and how Core Web Vitals look on a mid-range phone.
  • Long sessions: virtualizing a list that grows to 2,000 posts, and dropping media that scrolled far away.
  • Failure: retries with backoff, an offline banner, a send queue for chat, and what the page shows when one service is down.

Check your understanding · Exercise 4

It's minute 18 of "Design a chat app". Which topics deserve your next 15 minutes? Select all that apply.

How scope changes the RADIO time split

RADIO works for both shapes. The five letters stay; the minutes move. The RADIO framework lesson gives a default split for a 45-minute round: about 3 minutes of hellos, then 5 for Requirements, 8 for Architecture, 4 for Data model, 5 for Interface, and 15 for Optimizations, with 5 left for your questions. That default fits a feature question, which sits in the middle.

For the two archetypes, shift minutes from the parts that shrink to the parts that grow. The total design time stays at about 37 minutes.

A 45-minute round with 3 minutes of hellos and 5 for your questions. These match the time planner in the RADIO framework lesson. In a 60-minute round (5 minutes of hellos, 50 of design), the planner gives 7, 6, 5, 10, 22 for a component, 7, 11, 5, 7, 20 for a feature, and 7, 12, 7, 6, 18 for an app.
StepComponent (min)Feature, the default (min)App (min)
Requirements555
Architecture489
Data model445
Interface754
Optimizations (deep dives)171514
Total design time373737

Why each step grows or shrinks

  • Requirements stay about the same. Both shapes need the same short list: functional, non-functional, out of scope. The content differs (props and devices versus users and scale), not the length.
  • Architecture halves for a component. Three or four boxes inside the browser (input, popup list, controller, cache) take four minutes. An app needs the client layers, the API, a CDN, a real-time channel, and arrows between them.
  • Data model grows a little for an app. A component has internal state: query, activeIndex, isOpen, status. An app has entities and relations, a normalized store, and URL state.
  • Interface flips. For a component it's the main event: props, events, slots, and the keyboard map. For an app it's two or three endpoints with their paging and errors; component props get a sentence.
  • Deep dives keep the largest share in both. That's where levels are separated. A component's deep dives are inside the box (accessibility, races, virtualization). An app's are between client and server (pagination, caching, freshness, first load).
The prompt is a
Slot length
A bar chart of design minutes for a component question in a 45-minute slot: Requirements 5 minutes, Architecture 4 minutes, Data model 4 minutes, Interface 7 minutes, Deep dives 17 minutes. Dashed bars show the default feature split: 5, 8, 4, 5, 15.Requirements5 minArchitecture4 min (-4)Data model4 minInterface7 min (+2)Deep dives17 min (+2)dashed: the default split
Architecture shrinks and the Interface grows: the props and keyboard map are the product. The deep dives get the most time of any shape.

Checkpoints: requirements done by minute 8, the box diagram by minute 12, interface done and deep dives started by minute 23, wrap up by minute 40.

  • Requirements: props, states, devices, the accessibility bar, bundle budget
  • Architecture: 3 or 4 boxes in the browser: input, popup, controller, cache
  • Data model: internal state: query, activeIndex, isOpen, status
  • Interface: the main event: props, events, slots, keyboard map
  • Deep dives: accessibility, request races, long lists, positioning

Same letter, different drawing

The bigger change isn't the minutes. It's what you put on the whiteboard for each letter. A candidate who keeps the app-style drawing for a component, even with the right minutes, still spends Architecture drawing servers nobody asked about.

A matrix with the five RADIO steps as rows and two columns, component and app. Requirements: props, states, and devices for a component; users, scale, and offline for an app. Architecture: four boxes all in the browser, versus client, CDN, API, and push channel, highlighted for the app. Data model: query and activeIndex, versus normalized entities. Interface: props, events, and keys, highlighted for the component, versus three endpoints with cursors. Deep dives: accessibility, request races, and long lists, versus pagination, caching, and freshness, both highlighted.componentappRequirementsprops, states, devicesusers, scale, offlineArchitecture4 boxes, browser onlyclient, CDN, API, pushData modelquery, activeIndexentities, normalizedInterfaceprops, events, keys3 endpoints, cursorsDeep divesa11y, races, listspages, cache, freshness
Same five letters, different drawings. The highlighted cells are where each shape gets its extra minutes: the Interface for a component, the Architecture for an app, and the deep dives for both.

Check your understanding · Exercise 5

You're 20 minutes into "Design a date picker for our design system" and you've just finished a server diagram with a holidays API and a CDN. What's true? Select all that apply.

Worked example: an autocomplete, minute by minute

Here is how a strong 45-minute answer to "Design an autocomplete for our design system" spends its time. The full design is in the Design an autocomplete guide; this chapter shows only the shape of the answer and why each minute goes where it does.

Minutes 3 to 8: requirements

Confirm the shape first: "This is a shared component that many teams will drop into search boxes and forms, right?" Then ask about the data (local list or a server search, how many results, how fast the endpoint is), the inputs (keyboard, touch, screen readers), the browsers, and the bundle budget. Write down a short list:

  • Functional: show matches as you type, select with mouse, touch, or keyboard; works with a local list or a server search; custom option rows.
  • Non-functional: suggestions within 400 ms after typing stops on 4G; full keyboard and screen reader support (APG combobox); under 10 KB gzipped; works with server rendering.
  • Out of scope: the search backend and its ranking, multi-select chips (offer them as an extension).

Minutes 8 to 16: architecture and state

The architecture is four boxes, all in the browser: the input, the popup with its list, a controller that owns timing and the keyboard, and a small cache. One arrow leaves the browser, to the search function the parent passes in. That takes four minutes, and that's correct: there's nothing more to draw.

The state is just as small: query, items, activeIndex, isOpen, status (idle, loading, success, empty, error), and a cache of recent queries mapped to results. Say that the selected value can be controlled by the parent, which leads straight into the interface.

Minutes 16 to 23: the interface

This is the longest early step, and it should be. Write the props type from chapter 4, then the events, then the keyboard map: Down and Up move the active option, Enter selects, Escape closes the popup (and clears the box on a second press), Home and End move the cursor in the text, Tab leaves without selecting. Say how customization works (renderOption, a slot for the empty state).

Design an autocomplete: the board, step by stepStep 1 of 5: Requirements, minutes 3 to 8

A 45-minute timeline with the five RADIO steps for Design an autocomplete: Requirements from minute 3 to 8, Architecture from minute 8 to 12, Data model from minute 12 to 16, Interface from minute 16 to 23, Deep dives from minute 23 to 40. Below it, what is on the whiteboard so far, and a note with what the current step adds.RADIOminute 045minutes 3 to 8on the boardR: needs, a11y barshared component, many teamslocal list or server searchAPG combobox, under 10 KBout: ranking, multi-select
Confirm it's a shared component, then write the needs, the accessibility bar, and what's out of scope. About 5 minutes.

Requirements, minutes 3 to 8: Confirm it's a shared component, then write the needs, the accessibility bar, and what's out of scope. About 5 minutes.

Minutes 23 to 40: deep dives

Pick three, say why, and go deep. Each one is about something that happens inside the box:

  1. Stale responses. The user types rea, then reac; the rea response arrives last and overwrites the better list. Fix: abort the old request with AbortController and ignore any response whose query doesn't match the current one.
  2. Fewer requests. Debounce typing by about 200 ms, wait for 2 characters, and cache recent queries so backspacing is instant. Typing javascript drops from 10 requests to 1 or 2.
  3. Accessibility. Focus stays in the input; the active option is pointed to with aria-activedescendant; aria-expanded and aria-controls link input and list; a polite live region says "5 results". Test it with VoiceOver and NVDA, not only with a linter.

If time is left, mention long lists (cap at 10 or virtualize), popup positioning near the screen edge and above a phone keyboard, and input methods for Chinese or Japanese, where you must not search during composition. The Design a modal dialog guide follows the same shape: a tiny architecture, a large API section (open state, close reasons, initial focus), and deep dives on focus trapping, returning focus, and scroll locking.

Think first

Halfway through the autocomplete, the interviewer asks "so how does the search server work?" How deep do you go?

Worked example: a news feed, minute by minute

Now the same clock for "Design a news feed". The full design is in the Design a news feed guide. Compare where the minutes go with the autocomplete: Architecture more than doubles, the Interface shrinks to the network API, and the deep dives move from inside the box to between client and server.

Minutes 3 to 8: requirements

Cut scope early, because an app has more features than you can design: "I'll focus on reading the feed, liking, and commenting. Posting with media gets a short section. Profiles, messaging, and ads are out of scope." Then ask about scale and devices, and use a quick estimate (the Back-of-the-envelope numbers for frontend lesson shows how).

  • Functional: infinite scroll of posts with text and images; like and comment; see that new posts exist without losing your place.
  • Non-functional: first posts visible in under 2.5 seconds on a mid-range phone on 4G (LCP); smooth scrolling through 1,000+ posts; works on flaky networks; images don't shift the layout.
  • Out of scope: ranking (the server decides the order), ads, messaging.

Minutes 8 to 17: architecture

Draw the whole system in one picture: the browser with its view layer, a client store (query cache with normalized posts and users), a data layer that talks to the feed API, a CDN for images and static files, and a channel for new-post notices. Mark which page is server rendered. This takes about nine minutes, and every box will come back in a deep dive.

Minutes 17 to 26: data model and API

Name the entities: Post, User, Comment, and the feed as a list of post ids with a nextCursor. Say they're normalized, so a like updates the post everywhere it appears. Then give the API from chapter 5: GET /feed?cursor=...&limit=20, POST /posts/:id/like, GET /posts/:id/comments?cursor=.... Two sentences on why a cursor beats an offset: new posts at the top would shift offset pages and cause duplicates.

Note what isn't here: no PostCard props type, no keyboard map. If the interviewer wants a component, they'll ask, and you can zoom in later.

A sequence diagram between the feed view, the client store, and the feed API. The view asks the store for page 1. The store sends GET /feed?limit=20. The API answers with 20 posts and a nextCursor. The store gives the view post ids. Later the view reports that the bottom sentinel is visible. The store sends GET /feed?cursor=c2, and the API answers with 20 more posts and no duplicates. Then the API pushes a notice over server-sent events that 3 new posts exist, and the store tells the view to show a New posts pill.Feed viewClient storeFeed APIneed page 1GET /feed?limit=2020 posts + nextCursorpost idssentinel visibleGET /feed?cursor=c220 more, no duplicatesSSE: 3 new postsshow New posts pill
This is the picture an app question wants, where the autocomplete wanted a props type. Every arrow is a decision: a cursor instead of an offset, ids in the view and posts in the store, a pill instead of pushing posts under the reader.

Minutes 26 to 40: deep dives

  1. Loading and pagination. An IntersectionObserver sentinel near the bottom starts the next page before the reader gets there; the cursor guarantees no duplicates; one page in flight at a time.
  2. Long sessions. Virtualize the list so only the 10 to 20 posts near the viewport are in the DOM; reserve image space from the API's width and height so nothing jumps.
  3. Freshness. Poll a cheap "anything new?" endpoint (typically every 30 to 60 seconds) or listen on server-sent events; show a "New posts" pill instead of inserting posts above the reader.
  4. Instant likes. Optimistic update in the normalized store, rolled back with a toast if the request fails.

That's four deep dives in fourteen minutes, so each gets three or four minutes. That is normal for an app: breadth is part of the signal, and you go deepest on the one or two the interviewer leans into.

Design a news feed: the board, step by stepStep 1 of 5: Requirements, minutes 3 to 8

A 45-minute timeline with the five RADIO steps for Design a news feed: Requirements from minute 3 to 8, Architecture from minute 8 to 17, Data model from minute 17 to 22, Interface from minute 22 to 26, Deep dives from minute 26 to 40. Below it, what is on the whiteboard so far, and a note with what the current step adds.RADIOminute 045minutes 3 to 8on the boardR: scope, LCPread, like, commentout: ads, ranking, DMsLCP under 2.5 s on 4G1,000+ posts, smooth
Cut scope hard: reading, liking, commenting. Name the load target and the scale. About 5 minutes.

Requirements, minutes 3 to 8: Cut scope hard: reading, liking, commenting. Name the load target and the scale. About 5 minutes.

Check your understanding · Exercise 6

In the news feed answer, which of these belong in the deep dives rather than the earlier steps? Select all that apply.

Feature questions, zooming, and the mistakes that cost points

Real prompts don't always sit at either end. Feature questions mix both shapes, and good answers move between levels on purpose. This chapter covers the middle ground, how to switch levels cleanly, and the mistakes interviewers see most often.

Feature questions: two interfaces

A feature like a comment section has two interfaces. Facing the server, it needs an API: list comments with a cursor, post a comment, maybe a stream of new ones. Facing the host page, it's a component: postId, currentUser, an onCountChange event so the page header can update its comment count. Sketch both, briefly, and spend the deep dives on what makes this feature hard: threaded replies, optimistic posting, moderation states.

PromptShapeWhere the depth is
AutocompleteComponentRequest races, debouncing, caching, combobox keyboard support
Modal dialogComponentFocus in and out, inert background, scroll locking, stacking
Image carouselComponentLazy loading, swipe and keyboard, reduced motion, layout shift
Data tableComponentVirtualized rows, sorting and filtering API, sticky headers
Comment sectionFeatureThreads, paging replies, optimistic posting, moderation
Notification bellFeatureReal-time delivery, unread count across tabs, batching
File uploaderFeatureChunked uploads, resume after failure, progress, cancel
News feedAppCursor pagination, virtualization, normalized store, new posts
Chat appAppWebSockets, ordering, offline send queue, delivery receipts
Collaborative editorAppConflict resolution, presence, offline edits

Zooming in and out on purpose

Strong candidates change level during the round, and say when they do. In an app question, zoom into one component for a deep dive once the data flow is clear: the feed's virtualized list, the chat composer's send button states. In a component question, zoom out briefly to show where its data comes from, then come back.

The rule is to finish the level you're on before you leave it, and to announce the switch: "The data flow is in place. I'd like to zoom into the feed list for a few minutes, because that's where scrolling performance is won or lost." Without the announcement, the interviewer loses the thread, and a zoom looks like drifting.

A state machine with two pairs of states. In an app question: from Whole system to One component, on the transition announce, then zoom in; and back to Whole system when the point is made. In a component question: from Component API to Data source, when asked about data; and back to Component API after one or two sentences. A warning note at the bottom: zooming without saying so, or never coming back, makes the interviewer lose the thread.app questionWhole systemOne componentannounce, zoom inpoint made, zoom outcomponent questionComponent APIData sourceasked about dataone or two sentenceszoom without saying so, or never come back:the interviewer loses the thread
Each zoom is a round trip with a reason. Leave a level only after it's complete, say why you're leaving, and come back when the point is made.

Mistakes that cost points

  • Servers for a widget. Drawing a load balancer, database, and cache cluster for a date picker. The interviewer can't score any of it.
  • Props for a product. A careful PostCard type at minute 20 of a news feed while pagination and caching are still blank.
  • Happy path only. A component with no loading, empty, or error state, or an app where nothing ever fails.
  • Accessibility as a footnote. "And we'd add ARIA" at minute 44. In a component question, it's a main deep dive; in an app, at least name focus handling for route changes and dialogs.
  • Never confirming the shape. Spending ten minutes on the wrong kind of answer for an ambiguous prompt, when one question would have fixed it.

What changes with seniority

Junior candidates are expected to cover the basics of the shape they're given: a sensible props type, or a sensible API and box diagram. Mid-level candidates should pick the right emphasis without being told and handle the main states and failures. Senior and staff candidates spot the shape and scope it in the first minute, offer a default for ambiguous prompts, explain trade-offs before being asked, and zoom between levels cleanly. The What interviewers look for, by level lesson covers these signals in detail.

Check your understanding · Exercise 7

You're designing a comment section that teams can add to any article page. What should your Interface step include? Select all that apply.

Summary

  • Frontend prompts come in two main shapes: a component (one reusable piece of UI for other developers) and an app (a product with screens, a server, and changing data). Feature questions sit in between.
  • Two tests sort most prompts: who is the main user of the design, and does the hard part live inside one rectangle or between client and server?
  • Confirm the shape in the first minute with one question that offers a default. For ambiguous prompts like a rich text editor, pick a scope and say why.
  • In component questions, the interface is the product: props and events, controlled and uncontrolled, customization, every state, and the APG accessibility pattern.
  • In app questions, the hard parts are the client-server contract and data flow: endpoints and pagination, a normalized client store, freshness, first load, and failure.
  • The RADIO minutes move with scope: about 5, 4, 4, 7, 17 for a component and 5, 9, 5, 4, 14 for an app in a 45-minute round. Deep dives keep the largest share in both.
  • Zoom between levels on purpose and say so out loud: into one component in an app question, out to the data source in a component question.

In the interview

Questions interviewers ask about this. Answer each out loud first, then compare.

Question 1

You're asked to "Design a date picker." What do you ask first, and where does your time go?

Question 2

How would your answer to "Design an image carousel" change if the prompt were "Design Instagram"?

Question 3

In a component question, the interviewer asks how the data gets there. How deep do you go?

Question 4

How should the RADIO time split differ between a component question and an app question in a 45-minute round?

Question 5

The prompt is "Design a comment section for our blog platform." Is it a component or an app question?

References

Read next