Question presented to candidate: "You are joining a team with a 300-component Vue app. Everything lives in a handful of giant Pinia stores, half the bugs are stale data, and SSR is coming next quarter. How would you structure state management going forward?"
What a strong answer should cover:
- Classify state first: local UI state, subtree state, URL state, server state (cached copies of backend data), and true global client state. Each has a different best home.
- Keep state as local as possible: component
refs, composables, provide/inject for a subtree; the URL query for shareable view state. - Treat server state separately: a query cache (Pinia Colada, TanStack Vue Query or a small in-house layer) handles dedupe, caching, invalidation and loading/error state better than hand-written store actions.
- Pinia for global client state, split into small domain stores by feature, colocated with the feature; stores may use other stores inside actions/getters, with no cycles at setup time.
- SSR safety: no module-level mutable singletons; one Pinia (and one cache) per request; serialise state for hydration.
- Conventions that scale: store ids by feature, actions as the only writers for shared stores,
storeToRefsfor destructuring, tests per store.
Clarifying questions expected:
- "How much of the state is server data versus purely client-side?"
- "Which rendering mode is coming: SSR with hydration, or static generation?"
- "Do several tabs or users need to see the same data live?"
Code / implementation expected: Optional β a domain store depending on an app store, and a sketch of the layer diagram.