GraphQL PoC [DO NOT MERGE]#8232
Conversation
Adds a /dashboard-graphql variant that fetches all dashboard data via a single GraphQL query through @apollo/client. The existing dashboard at / is untouched. - codegen.ts with client-preset, reading schema.graphql - scripts/sync-graphql-sdl.mjs syncs SDL into a TS constant for the mock layer so the loader config is bundler-agnostic - MSW handler intercepts POST /graphql with @graphql-tools/mock when NEXT_PUBLIC_MOCK_GRAPHQL=true; toggle is independent of NEXT_PUBLIC_MOCK_API - ApolloProvider sits next to the Redux Provider in _app.tsx; auth link reads the redux token and applies addCommonHeaders, matching RTK Query - Paired with fidesplus graphql-poc-be@104cba76c Local PoC branch — do not push.
The Strawberry endpoint is mounted at /graphql, outside the /api/v1 prefix the existing rewrites cover, so against the real backend the client's POST /graphql would 404 on the Next dev server. Add a rewrite mirroring the existing /health one. Mock mode is unaffected — MSW intercepts /graphql before the rewrite. Local PoC branch — do not push.
ProtectedRoute redirects to / when useNav finds no active match for the path. Add the variant route to NAV_CONFIG as hidden (reachable by URL, not shown in the sidebar) so the PoC page is accessible. Local PoC branch — do not push.
NEXT_PUBLIC_FIDESCTL_API is /api/v1 in local dev (not empty as the client assumed), so the prior URI resolved to /api/v1/graphql and 404'd against the backend, which mounts GraphQL at the app root /graphql. Use the relative /graphql path so the Next rewrite proxies it to the backend and MSW still intercepts it in mock mode. Local PoC branch — do not push.
The dashboard at / now fetches through Apollo. Per-card queries (not one combined query) to preserve independent auth failure and progressive per-card loading, matching REST behaviour and the LLM-backed agent briefing's latency. - src/features/dashboard-graphql/queries.graphql: 8 per-card operations - src/features/dashboard-graphql/hooks.ts: drop-in replacements with the exact RTK hook names/signatures/return shapes, mapping camelCase gql responses onto the existing snake_case ~/features/dashboard/types so each card changes only its import path - 9 one-line import swaps in src/home/* - ApolloProvider moved into _app.tsx (inside Redux Provider) so the home dashboard subtree has it - deleted pages/dashboard-graphql.tsx + DashboardGraphqlView + the hidden nav entry; removed the monolithic dashboard.graphql - dashboard.slice.ts kept (update mutation stays on RTK) Local PoC branch — do not push.
The drop-in hooks rebuilt the mapped object every render, giving `data` a new reference each time. useInfiniteActivityFeed keys a setState effect on `data`, so it re-fired every render -> "Maximum update depth exceeded". Memoize each mapping on the raw query data (Apollo keeps a stable data ref until the result changes) so consumers see a stable identity. Local PoC branch — do not push.
Folds the six static dashboard cards (posture, trends, system coverage, privacy requests, astralis, agent briefing) into one combined query and defers agentBriefing — the slow LLM-backed field — so the dashboard paints on the first multipart chunk and the briefing banner arrives in a second chunk. priorityActions and activityFeed keep their own per-card queries; their interactive variables (dimension filter, infinite-scroll pagination) would otherwise force the whole combined query to refetch on every filter change or "load more". Apollo's HTTP link auto-negotiates multipart/mixed — no client config change. Apollo deduplicates concurrent useQuery(DashboardOverviewDocument) calls with identical variables into a single network request, so the six static drop-in hooks all share one POST. Requires the BE bump to strawberry-graphql 0.315.5 with enable_experimental_incremental_execution=True (paired commit on fidesplus graphql-poc-be). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
# Conflicts: # clients/admin-ui/package.json # clients/admin-ui/src/pages/_app.tsx
Dependency ReviewThe following issues were found:
Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned Files
|
Decisions live in the separate decisions doc; this file mostly duplicated that and held conversation-style context that isn't useful to readers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Run prettier --write on graphql codegen output and schema files to satisfy the admin-ui format:ci check. No behavior changes; only quote style and line-wrap adjustments to auto-generated files (schema.graphql, src/__generated__/graphql/*, schema-string.ts).
| awaitingResponse | ||
| risksIdentified | ||
| } | ||
| ... @defer(label: "agentBriefing") { |
There was a problem hiding this comment.
Try replacing @defer with a separate query. @defer requires graphql-core>=3.3.0a9 (alpha) on the backend. A separate DashboardAgentBriefing query achieves the same UX -- dashboard paints from DashboardOverview, and the slow LLM briefing arrives independently. The network cost is one additional small request vs. multipart streaming -- negligible for this use case.
Applied in #8250.
| import { DashboardGraphqlProvider } from "~/features/dashboard-graphql/DashboardGraphqlProvider"; | ||
|
|
||
| import store, { persistor } from "../app/store"; | ||
| import theme from "../theme"; |
There was a problem hiding this comment.
Try scoping ApolloProvider inside ProtectedRoute. Currently wraps the entire app tree including login/forgot-password pages. This creates an Apollo client for every visitor before auth. Moving it inside ProtectedRoute means no unnecessary client instantiation on unauthenticated pages, and the auth token is guaranteed available when the client is created.
Applied in #8250.
| ApolloClient, | ||
| createHttpLink, | ||
| InMemoryCache, | ||
| type NormalizedCacheObject, |
There was a problem hiding this comment.
Try moving the endpoint under /api/v1. /graphql at the app root needs a custom Next rewrite and sits outside existing CORS/proxy/middleware rules. /api/v1/plus/graphql is covered by the existing /api/v1/:first/:second* rewrite, and inherits all backend infrastructure.
Applied in #8250.
| @@ -0,0 +1,319 @@ | |||
| /** | |||
There was a problem hiding this comment.
Research note: is Apollo the right client for this? For read-only views with no mutations, Apollo's normalized cache provides little value -- there are no writes to propagate across views. The complexity tax of cache.modify, cache.evict, and partial cache hits may not be worth it.
RTK Query with a thin GraphQL fetcher (or TanStack Query) would be simpler for this use case and wouldn't require a second caching paradigm alongside RTK.
Source: TanStack Query vs SWR vs Apollo 2026, RTK Query Comparison
Not blocking -- just worth discussing before this ships.
Summary
Draft / PoC.
Wires the home dashboard at
/to GraphQL via Apollo Client, consuming the Strawberry endpoint from this fidesplus PR.DashboardOverviewquery for the six static cards, with@deferonagentBriefingso the dashboard paints on the first multipart chunk and the LLM-backed briefing banner arrives in a second chunk.priorityActionsandactivityFeedkeep their own per-card queries — their interactive variables (dimension filter, infinite-scroll pagination) would force the combined query to refetch on every change.dashboard.slice.tsis kept (mutations stay on RTK).Run it
Against the real backend (fidesplus on the paired branch must be running):
Mocks only, no backend required:
Open
http://localhost:3000/— dashboard is GraphQL-backed under thealphaDashboardfeature flag.Regen typed documents after SDL changes
Run this after
nox -s graphql_emit_schemaon the paired backend branch.Paired backend
ethyca/fidesplus#3618.
🤖 Generated with Claude Code