30% offEnding soon
FSD-009Frontend system design Premium

Design a Command Palette

Design a fast, accessible command palette with indexed search, stable ranking, nested scopes, async actions, and safe execution.

Intermediate 46 min read

Build the command palette around a stable command registry, a generation-tagged search pipeline, and an execution state machine. Keep DOM focus in the query input, identify the active result by command ID, discard stale provider responses, confirm risky work, and let the server authorize every sensitive action again.

A command palette is the keyboard doorway into a product. It may navigate to a project, run a local UI action, search remote entities, or start a server mutation. Those operations look alike in one result list, but they have different discovery, permission, latency, and failure contracts.

Start with stable command identities

Every result should resolve to a registered command ID, not a label or array position. Labels change with locale. Ranking changes as providers return. Virtualization changes which rows exist in the DOM. A stable ID lets the browser preserve the active result and dispatch the intended action through all of those changes.

The smallest useful model has four parts:

  • a registry describes command identity, labels, keywords, scope, permission hints, and execution type;
  • a search pipeline filters and ranks the commands visible in the current context;
  • a palette state machine owns the open dialog, query generation, active ID, nested scope, and execution status;
  • an executor resolves the chosen ID, validates fresh context, and performs navigation, a local action, or an authorized server operation.

Search returns references. It does not carry executable callbacks across a worker boundary or accept arbitrary action code from a remote provider.

The public interview prompt

Design a reusable command palette for a large signed-in web application. Explain:

  • keyboard shortcuts, focus containment, restoration, input method editors, and screen-reader semantics;
  • a versioned registry built from core commands, route-scoped commands, and allowed extensions;
  • local indexing, remote providers, ranking, deduplication, cancellation, and stale-result protection;
  • stable selection while results reorder, virtualization, nested command pages, and scroll restoration;
  • navigation, synchronous actions, confirmations, asynchronous mutations, retries, and idempotency;
  • loading, empty, partial, offline, and degraded states;
  • permissions, sensitive labels, auditability, performance, observability, testing, and rollout.

Assume 25,000 registered command definitions across lazy feature modules, with at most 3,000 visible to one user and five optional remote entity providers. These are design assumptions, not measured facts. A natural-language assistant, arbitrary plugin execution, macro recording, and replacing visible navigation are outside version one.

What the premium solution covers

The complete solution defines registry and provider contracts, a worker-backed index, explainable ranking, a generation ledger, nested scope frames, the active-descendant focus model, virtualization rules, IME handling, an execution state machine, confirmation and idempotency policies, server contracts, degraded behavior, privacy, observability, tests, rollout stages, and an interview scoring rubric.

Original media follows two query generations through local and remote results, compares ranking contributions, maps state ownership, and annotates the dialog focus contract. Deterministic labs let you change ranking context and exercise navigation, confirmation, failure, and retry policies without calling a live service.

Premium solution

Continue with the complete system design

Unlock the architecture, state machine, API contracts, original diagrams, positioning model, accessibility decisions, performance budgets, testing plan, rollout strategy, scoring rubric, and interview walkthrough.

  • Detailed, beginner-friendly explanation
  • Production failure modes and trade-offs
  • Mobile-friendly architecture diagrams
  • Senior and staff-level interview signals
Unlock Premium

Frequently asked questions

Is a command palette a dialog, combobox, or menu?
A common accessible structure is a modal dialog containing an editable combobox whose popup is a listbox. The dialog owns containment and focus restoration. The combobox owns query input and the active option. A menu is a worse fit when users type arbitrary search text.
Should command search run in a Web Worker?
Use the main thread for a small registry that filters within the interaction budget. Move indexing and scoring to a worker when profiling shows long tasks or when the searchable corpus is large. Keep command execution on the main application boundary.
How should a command palette rank results?
Start with deterministic text relevance, then add bounded boosts for current context and explicit user history. Filter authorization before ranking, use stable command IDs, and include a deterministic tie-breaker so results do not jump between keystrokes.
How do async commands avoid double execution?
Snapshot the active command ID and context, enter a running state, disable duplicate submission, and attach an idempotency key to server mutations. Retry only when the command contract says the operation is safe to repeat.
How should nested commands work?
Model nested pages as a stack of scopes. Each frame owns its title, query, active command ID, result generation, and scroll position. Escape pops one frame before it closes the whole palette.
What should happen during IME composition?
Update the input normally, but do not treat Enter or shortcut-like keystrokes as command execution while KeyboardEvent.isComposing is true. Search can wait for compositionend or use a product-tested incremental policy.