Skip to content

Teacher-portal data layer: router loaders now, pgxsinkit later — never react-query or TanStack DB

Status: accepted

The teacher portal’s offering-management pages need a data layer. The obvious 2026 default for a TanStack shop — @tanstack/react-query — is deliberately rejected, permanently, for this repo’s frontends.

  • v1 is online-only: each offering sub-route fetches through its TanStack Router loader, which calls the typed client functions in features/offerings/lib/client.ts; mutations call those functions and then router.invalidate(). No client-side cache layer, no manual state surgery.
  • The typed client functions are the seam. When offline teacher authoring becomes real, their internals become local reads/writes against PGlite synced by pgxsinkit (via packages/offline-data); their call sites survive unchanged.
  • The offline data layer is pgxsinkit, full stop. We are fully committed to it: the canonical source lives in this workspace, so we evolve it to fit our needs (keeping it generic — it is open source). @tanstack/react-query and @tanstack/db are not candidates and are never introduced — pgxsinkit was created precisely because TanStack DB’s persistence was not production-ready, and adding Query now would create a third data layer that is neither the present pattern nor the future one. (TanStack Router and other TanStack projects remain in use where relevant.)
  • The schema already anticipates teacher-side sync: learning_unit carries LWW columns and offering_membership is a pgxsinkit sync-entry table.
  • Teacher offline will never be all-or-nothing. Draft authoring (structure tree, assessment composition) is plausibly offline; roster invites, membership status, publishing (structure freeze), transactional sibling renumbering, and hard-delete eligibility are inherently server-anchored. This mirrors the Delivery Profile split (offline-complete vs server-anchored) already in the domain language.
  • Offline drafting is its own future design project (tree-edit conflict semantics under LWW — e.g. concurrent reparenting — are genuinely hard) and must not be introduced as a side effect of UX work.