Skip to content

feat(mapgen-studio): migrate client transport to oRPC, add TanStack Query client, and introduce Zustand viewStore#1610

Merged
mateicanavra merged 1 commit into
mainfrom
design/client-data
Jun 12, 2026
Merged

feat(mapgen-studio): migrate client transport to oRPC, add TanStack Query client, and introduce Zustand viewStore#1610
mateicanavra merged 1 commit into
mainfrom
design/client-data

Conversation

@mateicanavra

Copy link
Copy Markdown
Owner

All client-to-server traffic in Mapgen Studio now flows through the typed oRPC client (src/lib/orpc.ts) bound to the studio contract. Previously, the React app reached the backend through hand-rolled fetch calls against /api/* endpoints; after this change, zero manual fetch of /api remains anywhere in the client.

Transport migration — The three features/*/api.ts wrappers (civ7Setup, runInGame, mapConfigSave) have their transport swapped from fetch to orpcClient.* while their result envelopes ({ ok, error, statusCode, observedAt, details }) are preserved exactly. ORPCError.status reproduces the legacy statusCode (including the run-in-game 404 used for server-restart detection) and ORPCError.data carries details/observedAt. The live-runtime poll's two reads (civ7.live.status, civ7.live.snapshot) and the inlined civ7.setupConfig read are also migrated. The poll's request-key staleness gate, adaptive backoff, and abort plumbing are untouched — only the network call changed.

Client data layer — A QueryClient factory (src/lib/query.ts) is added with short staleTime, single retry, and refetch-on-focus, and the app is wrapped in QueryClientProvider in main.tsx with a single module-root instance.

View state consolidation — A new Zustand v5 viewStore (src/stores/viewStore.ts) becomes the single owner of browser-only view state: canvas grid/edge toggles, overlay selection and opacity, era mode, panel collapse, and selected stage/step. The scattered useState calls for this surface in App.tsx are replaced with useViewStore selectors; App.tsx holds no mirror. Setters accept a value or an updater function, making the migration a drop-in for existing setX((prev) => …) call sites. Server-owned data is never mirrored into Zustand. zustand@5.0.14 is added as a dependency.

@github-actions

Copy link
Copy Markdown

Railway preview (MapGen Studio): not provisioned for this PR.

Policy (Graphite stacks): previews are created only for the top-of-stack PR by default.

  • To force a preview for this PR: add label railway-preview
  • To suppress a preview: add label no-railway-preview

Debug: {"isClosed":false,"isFork":false,"suppress":false,"force":false,"isTopOfStack":false,"hasToken":true,"draft":false}

mateicanavra commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

This was referenced Jun 12, 2026

mateicanavra commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

Merge activity

  • Jun 12, 8:50 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 12, 9:03 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 12, 9:03 PM UTC: @mateicanavra merged this pull request with Graphite.

@mateicanavra
mateicanavra changed the base branch from design/server-orpc to graphite-base/1610 June 12, 2026 20:59
@mateicanavra
mateicanavra changed the base branch from graphite-base/1610 to main June 12, 2026 21:01
…ck Query + viewStore

Complete the client half of EVERYTHING-talks-oRPC (FRAME §4.7): the React client
now performs ZERO manual fetch of /api. All server-data callers route through the
typed oRPC client (src/lib/orpc.ts) bound to the studio contract.

- Add src/lib/query.ts (QueryClient factory) + QueryClientProvider in main.tsx.
- Migrate features/{civ7Setup,runInGame,mapConfigSave}/api.ts transport from
  fetch to orpcClient.*; result envelopes preserved by construction. ORPCError
  .status reproduces the legacy statusCode (run-in-game 404 restart detection);
  .data carries details/observedAt/server-id echo. Non-uniform status registry
  preserved.
- Migrate the live-runtime poll's three reads (civ7.live.status, civ7.live.snapshot,
  inlined civ7.setupConfig) onto the oRPC client. Request-key staleness gate,
  adaptive backoff, abort plumbing, and 200-with-embedded-{error} handling are
  unchanged — only the transport swapped. No fetch( remains in App.tsx.
- Introduce viewStore (Zustand v5) as the single owner of browser-only view state
  (canvas toggles, overlay selection, era mode, panel collapse, selected stage/step);
  App holds no useState mirror. Query results are never mirrored into Zustand.
- Defer the persisted authoring/run Zustand stores to the decomposition slice
  (localStorage schema is hard-core parity; safer moved alongside the component split).

OpenSpec: mapgen-studio-client-data (validated --strict).
Verify: tsc clean; vite build + worker-bundle pass; dev-server network shows only
POST /rpc/* (zero /api/*), live poll cycles over oRPC at 200, no console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mateicanavra
mateicanavra merged commit 280926a into main Jun 12, 2026
This was referenced Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant