How do you structure a large-scale UI project for reuse?
UI Developer
answer
A scalable UI project structure groups code by domain and extracts shared parts into versioned packages. Use a design token source, an audited component library, and pattern templates for forms and layouts. Keep components presentational; move data and effects into hooks/services. Adopt routing with lazy chunks, rigorous linting and tests, and Storybook docs so multiple apps compose consistent pages without duplication.
Long Answer
A large-scale UI project structure succeeds when organization mirrors the product. Separate foundations, components, patterns, and app shells, and govern change with tests and versioning so teams move fast without fragmenting the experience.
1) Repositories and boundaries
Use a mono-repo with workspaces. Create packages like @ui/tokens, @ui/components, @ui/patterns, and domain modules such as @feature/catalog. Each package owns build, tests, and changelog. Publish with semantic versioning; record owners.
2) Foundations: tokens and theming
Keep color, type, spacing, radius, elevation, and motion as tokens in one source. Generate CSS variables/JSON so platforms share values. Enforce contrast and reduced-motion policies. Provide light/dark and brand themes via composition.
3) Components: accessible building blocks
Ship an audited library with stable props/events, keyboard support, visible focus, and ARIA only when needed. Document states and compose/slot APIs. Pair components with Storybook examples, visual tests, and a11y checks. Offer headless variants for custom layouts.
4) Patterns: pages without reinvention
Codify flows—forms, list→detail, search/filters, empty/error/loading states. Patterns prescribe spacing, focus order, and timing so pages stay consistent across teams.
5) State and side effects
Keep views thin. Encapsulate network/storage in services and useQuery/useMutation hooks with retry, cancel, optimistic updates, and cache keys. Local UI state in components; domain data in per-feature stores. Centralize error boundaries and feedback utilities.
6) Routing, layouts, and code splitting
Provide app shells (top-nav, side-nav, workspace). Route maps per domain with nested layouts and capability guards. Split on routes and heavy widgets; lazy-load icons/charts; prefetch on intent. Adopt container queries and fluid spacing.
7) Performance and delivery
Set bundle and interaction budgets. Enable tree-shaking, vendor chunking, and SSR/ISR where useful. Animate transform/opacity; pause offscreen motion. Measure Core Web Vitals and block regressions in CI.
8) Documentation and discovery
Map Figma ↔ code with token previews and live examples. Ship READMEs, migration notes, and do/do-not guidance. Provide a searchable Storybook and a starter app.
9) Governance and evolution
Use RFCs for breaking changes; semver + codemods. Automate linting for tokens, a11y, and import boundaries. Track component usage and version drift; review new patterns.
10) Testing and observability
Unit test composables/components; e2e test key journeys; visually test themes/states. Log UI errors with correlation IDs; capture user timings; expose a support panel for triage.
With this structure, modules are decoupled yet coherent; components are reused, not copied; and pages stay consistent while teams scale delivery.
Table
Common Mistakes
Organizing by file type instead of domains, scattering intent. Using a single global store for everything, coupling unrelated screens. Fetching and mutating data inside components without retry, cancellation, or cache keys, making tests brittle. Inconsistent component props/events, so reuse collapses and consumers fork code. No tokens or drift between design and code, causing visual divergence. Skipping route-level code splitting and lazy assets, shipping megabundles that slow first interaction. Custom widgets lacking roles, focus, or keyboard support. CPU-only performance thinking with no Core Web Vitals gates. No docs or Storybook; teams guess and duplicate. No semver or codemods; upgrades break apps. Overusing will-change and heavy filters in animations, introducing jank.
Sample Answers
Junior:
I structure folders by domain, use a shared component library, and keep components presentational. I move data fetching into small hooks, write Storybook docs, and add keyboard support and focus states. I split routes for big pages and use tokens for color and spacing.
Mid:
I set up a mono-repo with packages for tokens, components, patterns, and domains. Props/events follow a contract; components ship tests and a11y checks. I add useQuery/useMutation for data with retry and cache keys, and per-feature stores. Routing uses nested layouts and lazy widgets; CI runs affected builds and visual tests.
Senior:
I treat the UI project as a product: semver releases, RFCs for breaking changes, and codemods. I publish themes from tokens, measure Core Web Vitals, and gate deploys. Telemetry shows component usage and version drift; we deprecate safely. Patterns encode forms, list→detail, and empty/error states so pages stay consistent across apps.
Evaluation Criteria
Strong answers describe layered structure: tokens → components → patterns → shells → governance. Look for a mono-repo or equivalent boundaries; a single source of tokens emitting CSS variables; accessible components with stable props/events; and patterns for forms, navigation, and states. Expect separation of presentation and effects via services/hooks, route-level code splitting, and performance budgets tied to Core Web Vitals. CI should run linting, unit/e2e, a11y, and visual tests; releases use semver with RFCs and codemods. Red flags: global store everywhere, technical foldering, ad-hoc props, no Storybook, megabundles, or upgrades that break consumers. Bonus: telemetry of component usage, starter apps, and a service catalog with owners and support channels. Evidence of Storybook adoption, design-token syncing, and accessible defaults signals maturity.
Preparation Tips
Create a small mono-repo with packages: @ui/tokens, @ui/components, @ui/patterns, and one domain. Generate CSS variables from tokens and wire light/dark themes with contrast and motion policies. Build five components (Button, Input, Dialog, Toast, Table) with Storybook docs, keyboard/focus tests, and visual snapshots. Codify two patterns (validated forms, list→detail) and a workspace layout. Add useQuery/useMutation utilities with retry, cancel, optimistic updates, and cache keys. Split routes and lazy-load icons/charts; set budgets for bundle and interaction. Integrate ESLint, a11y lint, unit/e2e tests, and affected-only CI. Publish the library with semver; write one RFC and a codemod for a breaking prop rename. Add dashboards for Core Web Vitals and error rates; include a support panel that surfaces env and flags for triage. Run a small usability review and capture copy, focus order, and empty/error state fixes. Document ownership, contribution guidelines, and a deprecation policy.
Real-world Context
A marketplace centralized tokens and a component library; brand changes shipped to three apps in two days and visual defects dropped. A fintech moved fetch logic into hooks and codified form patterns; validation errors fell and support tickets declined. A media platform introduced route-level code splitting and lazy icon packs; first interaction improved while feature teams shipped independently. A SaaS vendor adopted semver with codemods for breaking changes; upgrades no longer stalled releases. A public sector portal standardized accessible components and navigation patterns; keyboard success rates rose and reported barriers decreased. A global retailer added theming hooks and extension points; regional teams customized surfaces without forking. Observability tied component versions to Core Web Vitals; a regression in Dialog focus was caught within hours and fixed in a patch. Regular post-mortems and RFC reviews trimmed props and aligned APIs, cutting onboarding time and accelerating delivery.
Key Takeaways
- Organize by domains and extract shared UI into versioned packages.
- Encode decisions as tokens; ship accessible, stable components.
- Codify patterns so pages assemble fast and stay consistent.
- Keep components presentational; move effects to hooks/services.
- Govern with semver, RFCs, codemods, tests, and performance budgets.
Practice Exercise
Scenario:
You must stand up a shared UI foundation for three web apps (admin, customer, partner) in six weeks. Leadership demands visual consistency, accessibility by default, and easy reuse without copy-paste.
Tasks:
- Foundations: define tokens (color, type, spacing, radius, motion) in JSON; generate CSS variables; implement light/dark themes with contrast and reduced-motion policies.
- Library: build five primitives (Button, Input, Select, Dialog, Toast) and one composite (Combobox) with roles, focus trap, keyboard support, and Storybook docs; add prop/event contracts.
- Patterns: ship a validated form template, a list→detail view, and empty/error/loading states bound to tokens; include error copy and focus order rules.
- Data layer: create useQuery/useMutation utilities with retry, cancel, optimistic updates, cache keys, and typed errors; keep components presentational.
- Delivery: configure route-level code splitting and lazy icons; set budgets for bundle size and interaction latency; add visual and a11y tests to CI.
- Governance: publish as a versioned package; write one RFC and ship a codemod for a breaking prop rename; add import-boundary lint rules and a contribution guide.
- Observability: add an error boundary, log correlation IDs, and a support panel showing env and feature flags; create dashboards for Core Web Vitals and error rates.
Deliverable:
A runbook with the token table, component and pattern inventory, CI gates, dashboards, and a risk list; plus screenshots of before/after pages demonstrating consistency.

