Skip to content

chore(admin): generate typesafe API client + adopt TanStack Query #7638

@JohnMcLear

Description

@JohnMcLear

Spun out of #7601 review feedback from @SamTV12345.

Problem

The admin UI currently hand-writes fetch calls in useEffect throughout (UpdateBanner, UpdatePage, plus the existing settings/plugins/users pages). Two issues with this:

  1. Pattern is officially discouraged — see the React docs: https://react.dev/reference/react/useEffect#fetching-data-with-effects (no caching, no dedup, no race-condition handling, manual loading states).
  2. Endpoint shape is duplicated — every fetch site re-types the request and response by hand. We already publish a Swagger/OpenAPI spec that describes these endpoints authoritatively, so any drift between the spec and the hand-written types is a silent bug.

Proposal

Generate the admin's API client directly from the OpenAPI spec, and use TanStack Query as the runtime.

Toolchain:

  • openapi-typescript — generates a TS types file from src/node/hooks/express/swagger.ts output. Run as a build step; the result is checked in or generated pre-build.
  • openapi-fetch — typed fetch wrapper that consumes the generated types. Zero runtime overhead, ~3 KB gzipped.
  • openapi-react-query — thin TanStack Query bindings that derive query/mutation hooks from the same generated types. Caching, dedup, refetch-on-focus, devtools all come along for free.
  • @tanstack/react-query — the runtime.

Net result: every endpoint becomes one line — useQuery({ ...client.GET("/admin/...") }) — with full request/response inference and no hand-written types.

Scope

  • Wire the OpenAPI generator into the admin build pipeline (or the root pnpm build).
  • Add @tanstack/react-query + provider at the admin root, plus React Query Devtools in dev.
  • Migrate every useEffect+fetch site in admin/src/ to the generated hooks.
  • Replace if (!data) return null patterns with Suspense boundaries (useSuspenseQuery).
  • Document the codegen step in admin/README so contributors know how to regen after API changes.

Out of scope

  • Migrating the pad-side frontend (different bundle, different concerns).
  • Backend changes — the OpenAPI spec is the contract; if anything moves, that moves first.

Why now

Tracking out of #7601 specifically — that PR adds two new admin fetch sites, and bundling this migration into it would balloon the diff. Cleaner as a dedicated PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    AdminNeeds rewriteNeeds rewrite as it was improperly implemented.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions