Question presented to candidate: "You are starting a codebase several teams will work in for years. How do you organise it?"
What a strong answer should cover:
- Organise by feature, not by file type. Grouping every component in
/componentsand every hook in/hooksmeans one change touches five folders and nothing is co-located. - A feature folder owns its components, hooks, types, tests and data access, and exposes a deliberate public surface — usually a single index — so its internals stay internal.
- Dependency direction is the real architecture: features may depend on shared, shared may never depend on a feature, and features should not reach into each other's internals.
- Enforce it with tooling. Import-boundary lint rules turn a convention into a check; without them the structure decays under deadline pressure.
- Colocation beats categorisation — a component's test, styles and types belong beside it, so deleting the feature deletes all of it.
- Keep a genuine shared layer for design-system components and cross-cutting utilities, and be strict about entry: shared code is code that is genuinely reusable, not code nobody knew where to put.
- State placement: server state in a data-fetching layer, URL state in the URL, local UI state in the component. A global store is for the little that is genuinely global.
- Structure serves change: the test is whether a new engineer can find, modify and delete a feature confidently.
Clarifying questions expected:
- "How many teams, and will they own separate areas?" — that changes how hard the boundaries need to be.
- "Is there a framework with its own routing conventions?" — that constrains the top level.
Code / implementation expected: No. A folder tree and the dependency rules are the answer.