BigQuery Query Console Redesign โ
Status: Draft Date: 2026-05-03 Scope: Admin portal โ /admin/analytics/bigquery/console
Goal โ
Replace the current Query Console layout with a tabbed-rail / work-surface structure that makes the editor and results the primary work area, unifies reference content (schema, saved queries, history) into a single collapsible rail, and treats result tables as a first-class viewing experience instead of an afterthought.
Why โ
The current console has four issues that compound:
- Layout fights itself. Schema browser and editor share a row, but results render under the editor in the same right-hand column โ so result tables get a narrow strip while the schema browser holds full vertical space.
- Wasted vertical space. Schema, editor, saved queries, and built-in reports all stack as full-width sections; running a saved query and seeing results requires significant scrolling.
- Flat hierarchy. Limit pills, section headers, cards, and results all carry equal visual weight.
- Results presentation is weak. Columns aren't sized to content, long UUIDs wrap into multiple lines of mush, no way to expand a row, no copy-CSV, no fullscreen.
Built-in reports also live on this page today but are moving to their own page (separate work).
Out of Scope โ
- Built-in reports section โ being removed from the console; lives on its own page (separate effort).
Reference Docs ยท Export Status ยท Query Console ยท Scheduled Reports ยท Data Retentionsub-nav (BigQueryTabs) โ unchanged.- Backend / API changes for query execution. Existing
runBqQueryRaw,estimateBqQueryRaw,saveQuery,deleteSavedQuery, schema-fetch endpoints stay as-is. - Authentication / authorization. No changes to admin role gating.
Layout โ
A three-zone shell:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Toolbar: โถ Run Estimate Save Format Clear [limits] โถ โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Tabbed rail โ Editor โ
โ โ โ
โ Schema โ โโ drag handle โโ (resizes editor / results split) โ
โ Saved (n) โ โ
โ History โ Cost & job meta strip โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ [searchโฆ] โ โ Results toolbar (filter ยท CSV ยท download ยท โถ) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ listโฆ โ โ Results table (resizable cols, click to expand)โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโToolbar โ
Single horizontal bar at the top of the work surface.
- Run (primary, accent-colored). Keyboard:
Cmd/Ctrl+Enter. - Estimate โ runs dry-run against current SQL.
- Save โ opens the existing save-query inline form.
- Format (ghost) โ formats the SQL in the editor via the
sql-formatterpackage (BigQuery dialect). - Clear (ghost) โ empties the editor (with undo via the editor's own history).
- Limits pill โ collapses the three pills (
SELECT only,1 GB,5k rows) into one compact pill (SELECT only ยท 1 GB ยท 5k rows); full text on hover via title attribute. - Fullscreen toggle (right side) โ CSS-only: hides the admin left sidebar and
BigQueryTabspage tabs so the console fills the browser viewport. Browser chrome / URL bar stay.Escexits. State is local to the component โ does not persist across navigation.
Tabbed Rail (left) โ
Single rail with three tabs. Width is resizable via a drag handle on the right edge; width persists per admin in localStorage.
Schema tab โ current SchemaBrowser content. One filter input that searches across datasets / tables / columns. Click a column or table to insert at cursor in the editor.
Saved tab โ current SavedQueriesPanel content, with the count badge in the tab label. Each entry shows name, SQL preview, author, timestamp, and Load/Delete actions. "Load into editor" replaces editor contents.
History tab โ new. Last 25 successful runs by the current admin, stored in localStorage (key: bq-console:history:<adminId>). Each entry: SQL snippet, timestamp, scan size, runtime. Click to load into editor. Cleared via a "Clear history" link in the tab header.
The rail is collapsible to a thin icon strip via a chevron in the rail header; collapsed state persists.
Work Surface โ
Editor. Existing RawSqlEditor component, retained as-is for SQL input. Drag handle along its bottom edge resizes the editor / results split; ratio persists.
Cost & job meta strip. Persistent strip between editor and results showing the most recent estimate (โ Last estimate: 711 KB ยท $0.000003) and the most recent job result (Job: 1.2s ยท 10 rows ยท cache miss). Errors render here inline (red text + icon) instead of in a separate ErrorCard below the results.
Results.
- Results toolbar: row-filter input (client-side substring filter across all columns), Copy CSV, Download CSV, Fullscreen (toggles same fullscreen as the toolbar button).
- Results table: existing
QueryResultTableextended with column resize (drag column-edge; widths persist per query name when applicable), and row-click to expand. The expand panel renders the row as a key/value list with full untruncated values (handles long UUIDs cleanly without wide columns). - Empty state: "Run a query to see results" with a hint about
Cmd/Ctrl+Enter. - Loading state: skeleton rows + a subtle pulsing accent on the Run button.
Component Breakdown โ
The current BigQueryWorkspace.jsx is ~1530 lines and combines export status, retention, scheduled reports, query console, schema browser, saved queries, raw editor, and result rendering. Touching it for this redesign without splitting will compound the problem.
Refactor as part of this work โ only the Console-related pieces:
apps/admin/src/admin/analytics/
โโโ BigQueryWorkspace.jsx # router shell, kept (other panels stay)
โโโ console/
โ โโโ ConsolePanel.jsx # orchestrator; replaces in-file ConsolePanel
โ โโโ ConsoleToolbar.jsx # Run / Estimate / Save / Format / Clear / limits / fullscreen
โ โโโ ConsoleRail.jsx # tabbed rail (Schema ยท Saved ยท History)
โ โโโ ConsoleEditor.jsx # wraps RawSqlEditor + the resize handle
โ โโโ ConsoleMetaStrip.jsx # estimate / job meta / inline errors
โ โโโ ConsoleResults.jsx # results toolbar + table + row-expand
โ โโโ HistoryPanel.jsx # rail's history tab
โ โโโ useConsoleState.js # editor SQL, last estimate, last job, error
โ โโโ useConsoleHistory.js # localStorage history hook
โ โโโ useConsolePersistence.js # rail width/collapsed, editor split ratio
โโโ (existing files for ExportStatus / Schedule / Retention untouched)SchemaBrowser, SavedQueriesPanel, RawSqlEditor, QueryResultTable, ErrorCard, ResultMetaFooter, SectionHeader, formatBytes, and structuredError are all only used by the Console flow today (verified: ExportStatusPanel, ScheduledReportsPanel, and DataRetentionPanel don't reference them). They move into apps/admin/src/admin/analytics/console/ and are deleted from BigQueryWorkspace.jsx. The orchestrator (ConsolePanel) is the only new top-level component the router renders for the console route.
useConsoleState is the single source of truth the toolbar, editor, meta strip, and results all read/write through. No prop-drilling chains.
Persistence โ
Per-admin localStorage keys (namespaced by admin id):
bq-console:rail:widthโ pixel width of the railbq-console:rail:collapsedโ booleanbq-console:rail:active-tabโ'schema' | 'saved' | 'history'bq-console:editor:heightโ pixel height of the editor panebq-console:historyโ array of{ sql, ts, scanBytes, durationMs }, capped at 25bq-console:column-widths:<queryFingerprint>โ optional, per-query column widths
A query "fingerprint" is a hash of the SQL text after format-normalization โ column widths only persist for queries that re-run with stable shape.
Keyboard โ
Cmd/Ctrl+Enterโ RunCmd/Ctrl+Sโ Save (opens existing save form)Cmd/Ctrl+Eโ EstimateCmd/Ctrl+Kโ focus rail search inputEscโ collapse rail (when not in an input)Esc(in fullscreen) โ exit fullscreen
Error Handling โ
- Query errors (BigQuery rejection, timeout, scan-cap exceeded): render in the cost/job meta strip as inline error text with the existing
structuredErrorshape. - Schema fetch failure: existing behavior preserved โ error card inside the Schema tab.
- Saved-query fetch failure: error card inside the Saved tab; rest of the console remains functional.
- History corruption (bad JSON in
localStorage): silently reset and continue. - Network offline: Run/Estimate buttons disable; toolbar shows a small "offline" pill. Rail tabs (Schema, Saved, History) remain functional for any data already cached, but show a stale-data hint where applicable.
Testing โ
Existing tests in apps/admin/src/admin/analytics/__tests__/ for the BigQuery flow continue to pass. New tests:
ConsolePanel.test.jsxโ rail tab switching; toolbar wiring; meta strip updates after estimate/run; row expand toggles.useConsoleHistory.test.jsโ capacity cap; corruption recovery; ordering.useConsolePersistence.test.jsโ width/height persistence; reset to defaults when keys missing.- Storybook story for
ConsolePanelcovering: empty / loading / results / error / fullscreen states.
Visual regression isn't currently set up for this area; not adding it as part of this work.
Migration / Rollout โ
Single PR. No feature flag โ admin-only surface, low blast radius, instant rollback by revert. Manual smoke check:
- Schema browser inserts at cursor as before.
- Saved queries load into editor as before.
- Estimate and Run produce the same response shapes.
- Errors render readably.
- History entries appear after a run and survive a page reload.
- Resize handles persist across reloads.
Decisions Made โ
These started as open questions and are now resolved:
- History storage โ
localStorageper admin. Saved queries already use Firestore (adminSavedQueries), but history is per-device ephemera (recent runs by the current admin) and doesn't justify Firestore writes on every successful run. Revisit if admins request cross-device history. - SQL formatting โ Ships with
sql-formatter(BigQuery dialect). Adds the Format button as a real feature in v1, not a follow-up. Bundle cost (~25 KB gz) is acceptable for an admin-only surface. - Fullscreen โ CSS-only toggle. Hides the admin left sidebar and
BigQueryTabspage tabs; console fills the browser viewport. Matches the BigQuery web UI pattern.Escexits.
New Dependency โ
sql-formatter(npm) โ added toapps/adminfor the Format button. BigQuery dialect.