Adopt TanStack as the frontend data/forms/tables layer #43

Closed
opened 2026-06-14 13:23:27 +00:00 by james · 0 comments
Owner

Pick a single, consistent set of primitives for client-side server state, form handling, and tabular data in the PWA before the feature tickets in epics #4 and #5 start landing. Picking late means every feature ticket has to make this call locally and the codebase ends up with three patterns for the same problem.

"UI system" here means the data/forms/tables layer, not the component/styling library. TanStack is headless — it pairs with whatever component library we settle on for visual primitives; this ticket doesn't pre-empt that decision.

Scope

  • TanStack Query for server state (fetching, caching, invalidation, mutations). Provider mounted at the app root.
  • TanStack Form for form state and validation across the editor surfaces (Profile, Person, Organization, Note, etc.).
  • TanStack Table for tabular displays (Skills, Education, Jobs, Contracts, Projects, People, Organizations list views).
  • An ADR comparing TanStack to the alternatives — see below for the comparison axes the ADR must cover.
  • One reference end-to-end pattern in the codebase: a route that fetches with Query, edits with Form, and lists with Table, against the existing DB abstraction. Subsequent feature tickets follow that pattern.
  • Documentation update: CLAUDE.md "Stack defaults" section adds the chosen pieces.

Out of scope (call out in the ADR so it's not relitigated)

  • TanStack Router and TanStack Start. Carol already uses Next.js App Router (see CLAUDE.md). Swapping routers is a separate, much larger decision.
  • Picking the component/styling library (shadcn/ui, Mantine, MUI, hand-rolled). That's a sibling ticket.
  • Migrating any feature code that doesn't exist yet. This ticket lands the foundation and the reference pattern; feature tickets adopt it as they're built.

ADR requirements

The ADR must compare TanStack against the realistic alternatives on each axis we actually care about:

  • Server state — TanStack Query vs SWR vs RTK Query vs "just RSC + Server Actions, no client cache".
  • Forms — TanStack Form vs React Hook Form vs Formik vs Conform vs hand-rolled.
  • Tables — TanStack Table vs AG Grid Community vs MUI X DataGrid vs hand-rolled.
  • The bundle/cohesion trade-off of taking the three TanStack pieces as a set vs mixing best-in-class per axis.
  • Compatibility with Next.js App Router and our PWA / offline-shell story — Query's offline + persistence story matters here.

For each axis: name the option, list the realistic pros/cons in our context (multi-user self-hosted Next.js app with strict per-user data isolation, both SQLite and Postgres backends), and pick one with the reason stated. Follow the established ADR format from docs/adr/0001-record-architecture-decisions.md.

Acceptance criteria

  • ADR written and accepted, comparing TanStack against the alternatives listed above on each axis. Linked from docs/adr/README.md.
  • TanStack Query Provider mounted at the app root; query client config (default stale time, retry policy, devtools in dev only) lives in a single module.
  • One reference route in the codebase exercises the full Query + Form + Table pattern against the DB abstraction.
  • The reference route's data path is tested under both DB engines per the existing convention.
  • CLAUDE.md "Stack defaults" updated to name TanStack Query / Form / Table as the chosen primitives.

Part of epic #3. Depends on #18 (PWA configuration). Should land before #21 (Profile) so the feature tickets in epics #4 and #5 can build on the reference pattern.

Pick a single, consistent set of primitives for client-side server state, form handling, and tabular data in the PWA before the feature tickets in epics #4 and #5 start landing. Picking late means every feature ticket has to make this call locally and the codebase ends up with three patterns for the same problem. "UI system" here means the **data/forms/tables layer**, not the component/styling library. TanStack is headless — it pairs with whatever component library we settle on for visual primitives; this ticket doesn't pre-empt that decision. ## Scope - **TanStack Query** for server state (fetching, caching, invalidation, mutations). Provider mounted at the app root. - **TanStack Form** for form state and validation across the editor surfaces (Profile, Person, Organization, Note, etc.). - **TanStack Table** for tabular displays (Skills, Education, Jobs, Contracts, Projects, People, Organizations list views). - An ADR comparing TanStack to the alternatives — see below for the comparison axes the ADR must cover. - One reference end-to-end pattern in the codebase: a route that fetches with Query, edits with Form, and lists with Table, against the existing DB abstraction. Subsequent feature tickets follow that pattern. - Documentation update: CLAUDE.md "Stack defaults" section adds the chosen pieces. ## Out of scope (call out in the ADR so it's not relitigated) - **TanStack Router and TanStack Start.** Carol already uses Next.js App Router (see CLAUDE.md). Swapping routers is a separate, much larger decision. - Picking the component/styling library (shadcn/ui, Mantine, MUI, hand-rolled). That's a sibling ticket. - Migrating any feature code that doesn't exist yet. This ticket lands the foundation and the reference pattern; feature tickets adopt it as they're built. ## ADR requirements The ADR must compare TanStack against the realistic alternatives on each axis we actually care about: - **Server state** — TanStack Query vs SWR vs RTK Query vs "just RSC + Server Actions, no client cache". - **Forms** — TanStack Form vs React Hook Form vs Formik vs Conform vs hand-rolled. - **Tables** — TanStack Table vs AG Grid Community vs MUI X DataGrid vs hand-rolled. - **The bundle/cohesion trade-off** of taking the three TanStack pieces as a set vs mixing best-in-class per axis. - **Compatibility with Next.js App Router and our PWA / offline-shell story** — Query's offline + persistence story matters here. For each axis: name the option, list the realistic pros/cons in *our* context (multi-user self-hosted Next.js app with strict per-user data isolation, both SQLite and Postgres backends), and pick one with the reason stated. Follow the established ADR format from `docs/adr/0001-record-architecture-decisions.md`. ## Acceptance criteria - [ ] ADR written and accepted, comparing TanStack against the alternatives listed above on each axis. Linked from `docs/adr/README.md`. - [ ] TanStack Query Provider mounted at the app root; query client config (default stale time, retry policy, devtools in dev only) lives in a single module. - [ ] One reference route in the codebase exercises the full Query + Form + Table pattern against the DB abstraction. - [ ] The reference route's data path is tested under both DB engines per the existing convention. - [ ] CLAUDE.md "Stack defaults" updated to name TanStack Query / Form / Table as the chosen primitives. Part of epic #3. Depends on #18 (PWA configuration). Should land before #21 (Profile) so the feature tickets in epics #4 and #5 can build on the reference pattern.
james closed this issue 2026-06-15 13:26:02 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#43
No description provided.