Carry the landing-page redesign into apps/docs so the marketing site and
the docs site share one visual language (OKLCH hue 250°, Geist Mono,
bordered surfaces, no glass).
- Rewrite src/styles/app.css around an OKLCH token layer that feeds into
Fumadocs's --fd-* variables, so the sidebar, TOC, navbar, search, code
blocks, callouts, and tables all pick up the neat palette automatically
- Remove AI design tells: gradient-text class, glass/glass-card,
border-flow conic ring, accent-glow, terminal-cursor blink, animate-float,
noise overlay, pre::before gradient stripe, text-shadow link glow
- Replace 3px side-stripe callouts with tinted borders + tinted backgrounds
- Drop the 2px border-left on the active sidebar item; use bg tint instead
- Redesign docs landing (routes/index.tsx): kill the spring-rotating book
globe, floating blurred blobs, text-8xl uppercase title, and border-flow
feature cards. Replace with a kicker, tight headline, two CTAs, and a
numbered 01-05 section index (Getting Started -> Reference)
- Tone down NotFound: drop the 12rem layered watermark 404; keep the
terminal error line as a proper token-colored <pre>
The test hard-coded REPO_ROOT/node_modules/@ai-sdk. That works locally
because historical installs hoisted there, but apps/desktop/.npmrc has
shamefully-hoist=true, which on a clean CI install puts @ai-sdk under
apps/desktop/node_modules/ instead. Result: zero packages discovered,
test fails with "expected 0 to be greater than 0" — guarding nothing.
Resolve via createRequire(apps/desktop/package.json) so we ask Node
itself where @ai-sdk/openai lives, then walk siblings from there.
Also scan every node_modules/@ai-sdk on the path up to the monorepo
root so nested copies (ai-v5 aliases, etc.) can't hide a bad version.
Adds a third "discovers installed @ai-sdk packages" assertion so a
broken walker is flagged directly instead of causing spurious
downstream passes.
v0.21.0 ships a TypeError at require time:
(0, import_provider_utils6.createProviderToolFactoryWithOutputSchema)
is not a function
Cause: PR #158 added @ai-sdk/xai, @ai-sdk/mistral, @ai-sdk/deepseek.
All three pull @ai-sdk/provider-utils@4, while core ai@5 is pinned to
@ai-sdk/provider-utils@3. pnpm hoisting + electron-builder's asar pack
pick the wrong version at runtime and the app refuses to open.
Fix: drop the three SDK packages. All three services expose
OpenAI-compatible endpoints, so route them through createOpenAI with
the matching base URL — same pattern GLM and Ollama already use. User-
facing provider list is unchanged.
Also extract the provider switch into ai-providers.ts so it can be
unit-tested without pulling in Electron, and:
- ai-providers.test.ts smoke-tests createProviderClient for every
AIProvider. Catches any future require-time crash from an @ai-sdk
package.
- ai-deps.test.ts walks node_modules/@ai-sdk and asserts every package
agrees on the provider-utils major version. This is the invariant
that #158 violated; the suite now fails fast if it breaks again.
CI guardrails:
- New ci.yml runs typecheck + tests on every push/PR to main. There
was no PR check before, which is how #158 landed green.
- build.yml and build-artifacts.yml gate all platform builds behind
a new `verify` job running the same checks, so a broken main can
never produce a release artifact.
- Artifact workflow now uses --frozen-lockfile like the release one.
Replaces TanStack's internal single-column sort with a chip-based
multi-sort system parallel to the existing Smart Filter Bar. Click or
shift-click column headers to toggle/append sorts; ⌘⇧S focuses the bar.
Each chip carries a type-aware mode (natural, length, absolute, byMonth,
byDayOfWeek, byTime, random) and a nulls-first/last toggle. Chips
reorder by drag or ⌥/⌘+←→ for keyboard users. Random mode uses a
seeded mulberry32 stream per chip; the dice icon rerolls the seed.
SortChip is a discriminated union so random chips require a seed at
compile time. applySorts takes the columns array so the default-mode
comparator dispatches strictly by declared type — no cross-type sniffing
that silently reorders string columns as numbers or dates. Invalid
dates in byMonth/byDayOfWeek/byTime route through the nulls-position
path rather than sorting as phantom bucket -1.
Adds pagination reset when sort or filter chips change so users don't
land on an empty page. 35 unit tests cover comparator paths, null
handling, stable-sort invariant, and toggleColumnSort cycle semantics.
Remove duplicate search inputs from Schema Explorer and Query History
since the omnibar already covers both. Fix omnibar spring bounce easing
to smooth expo ease-out under 200ms. Consolidate Quick Query's identical
dual buttons into one, remove its Recent section that duplicated History.
* feat(step): add shared types for step-through sessions
* feat(step): add statement parser with line-range metadata and DDL detection
* feat(step): add StepSessionRegistry with state machine and lifecycle management
Implements the session registry that holds open DB clients across user-pause gaps,
managing state transitions (paused/running/errored/done) for multi-statement step-through.
Also fixes root test script and excludes pre-broken sqlite native module tests from vitest.
* feat(step): add IPC handlers and wire session registry to app lifecycle
* fix(step): widen state type to avoid stale TS narrowing in continue()
* feat(step): expose step IPC via window.api.step
* feat(step): add Zustand store for step-through session state
* feat(step): add ribbon component with progress, controls, and keyboard shortcuts
* feat(step): add pinned + current results tab strip
* feat(step): wire Step button, ribbon, decorations, and breakpoint gutter
* fix(step): register Monaco commands for keybindings + sync cursor from server
Replace window-level keydown listener for Cmd+Shift+Enter with a Monaco
addAction registration so it takes precedence over Monaco's built-in Shift+Enter
handling. Also adds in-session Shift+Enter (next) and Escape (stop) as Monaco
actions, active only while a step session is running.
Add cursorIndex to all step response types (NextStepResponse, SkipStepResponse,
ContinueStepResponse, RetryStepResponse) and populate it from the server in
step-session.ts. The store now uses the server-provided value instead of
computing cursorIndex + 1 on the client, eliminating the 0/3 counter drift bug.
* fix(notebook): index result rows by column name
Rows from window.api.db.query are Record<string, unknown>[], not unknown[][].
ResultTable was calling row.map, throwing TypeError at runtime.
* feat(notebook): syntax highlighting via Monaco SQLEditor
Replace plain textarea/pre with the existing SQLEditor in compact mode
so notebook SQL cells get syntax highlighting, autocomplete (schemas,
keywords, functions), and the same theme as the main query editor.
Editor height grows with content up to 400px.
Pinned results are stored as unknown[][] but the renderer now indexes
rows by column name, so convert in both directions when pinning and
when rendering pinned snapshots.
* feat(notebook): drag-to-reorder cells with dnd-kit
Wrap the cells map in DndContext + SortableContext (vertical strategy)
and make NotebookCell sortable. Drag listeners attach only to the grip
button so Monaco editor pointer events keep working. Calls existing
reorderCells store action on drop, persisting the new order.
* fix(step): propagate real errors, clean up failed starts, harden cleanup
- Extend IPC response types with SessionSnapshot base + error fields
- start() wraps connect+BEGIN with cleanup on failure (prevents connection leak)
- continue() catch logs + sets errored state (no more silent swallows)
- executeCurrent logs errors and includes them in response
- stop() reports rollbackError so UI can surface ROLLBACK failures
- before-quit preventsDefault + awaits cleanup (3s timeout)
- parse-statements fallback path logs, computes correct endLine, stops silent drift
- Replace 'Query failed' placeholder in store with actual error message
- stoppedAt is now number | null (no more -1 sentinel)
* fix(step): renderer polish — toasts, Escape hijack, monaco bundle size
- Gate Step button and Monaco action to postgresql-only connections
- Toast on all IPC failures in step-store (replaces console.error)
- Surface ROLLBACK errors from stop() via destructive toast
- Roll back optimistic breakpoint state on setBreakpoints IPC failure
- Remove global Escape keydown listener (Monaco already handles it)
- Remove 'monaco-editor' namespace import; use onMount's monaco arg instead
(drops ~1-2MB from renderer bundle)
* test(step): add coverage for critical gaps
- start() cleanup on connect/BEGIN failure
- Empty/whitespace SQL rejection without creating a client
- Concurrent next() race (may reveal known limitation)
- Continue with breakpoint at current cursor (skip-own-breakpoint semantics)
- stop() idempotency
- retry() state guards (paused, done)
- skip on last statement transitions to done
- Parser: dollar-quoted blocks with internal semicolons
- Parser: duplicate statement bodies get distinct lines
- Parser: CRLF line endings
- Parser: no trailing semicolon on last statement
* feat(intel): add Schema Intel one-click diagnostics surface
Introduces a new "Schema Intel" tab that runs a configurable set of
read-only diagnostic queries against the active connection and surfaces
actionable findings (tables without PKs, missing FK indexes, duplicate /
unused / invalid indexes, bloated tables, never-vacuumed tables,
nullable FKs). Each finding includes a human-readable title, detail,
and — where possible — a suggested SQL fix that can be copied or opened
in a new query tab.
The feature ships a DatabaseAdapter.runSchemaIntel method with
implementations for PostgreSQL (full check set), MySQL (core checks
over information_schema), and MSSQL (tables without PK); SQLite is
stubbed and returns skipped entries.
Accessible from the sidebar's Automation & Monitoring group when a
connection is active.
https://claude.ai/code/session_01BitYEUsn3DiiT8LAgQdwUV
* chore: fix pre-existing typecheck and lint errors
- Rename unused filter callback param in sidebar-omnibar to `_value` so
it clears TS6133 under `noUnusedParameters`.
- Teach the desktop ESLint config to ignore underscore-prefixed
arguments / variables / caught errors / destructured array entries,
which is the convention already used throughout the codebase
(e.g. `(theme, _background) => ...` in health-monitor).
After this commit the desktop workspace typechecks and lints with 0
errors.
https://claude.ai/code/session_01BitYEUsn3DiiT8LAgQdwUV
* fix: let query errors propagate to orchestrator skip list
Remove try/catch from safeRun (renamed to runQuery) in all three
schema-intel adapters so that permission failures, missing extensions,
and syntax errors bubble up to the per-check try/catch in the
orchestrator and appear in the skipped array.
Also remove unused SchemaIntelBadge export.
* fix: apply CodeRabbit auto-fixes
Fixed 2 file(s) based on 3 unresolved review comments.
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
- "+" button now opens a menu with "New notebook" and "Import .dpnb…"
- File picker accepts .dpnb files, parses and recreates the notebook
with all cells and pinned results intact
- Fix type narrowing in tab-query-editor (early return for notebook tabs)
* feat(notebooks): add shared types for notebooks and cells
* feat(notebooks): add SQLite storage layer with full CRUD
Implements NotebookStorage class backed by better-sqlite3 with WAL mode,
foreign-key cascading deletes, and full CRUD for notebooks and cells.
* feat(notebooks): add IPC handlers for notebook CRUD
* feat(notebooks): add preload bridge for notebook IPC
* feat(notebooks): add NotebookTab type and createNotebookTab action
Adds 'notebook' to TabType union, NotebookTab interface, notebookId to
PersistedTab, createNotebookTab action with deduplication, persistence
handling, and notebook type guards in tab-query-editor.tsx.
* feat(notebooks): add Zustand store for notebook state management
* feat(notebooks): add NotebookEditor component and wire into TabContainer
* feat(notebooks): add sidebar section for browsing and creating notebooks
* feat(notebooks): add export functions for .dpnb and Markdown formats
* feat(notebooks): add NotebookCell component and dependencies
Add react-markdown and remark-gfm for markdown cell rendering.
NotebookCell handles SQL execution, markdown rendering, result
pinning, and keyboard shortcuts.
* fix: address review feedback for SQL notebooks
- Wrap JSON.parse in try/catch for corrupt pinned_result data
- Fix IPC type mismatches: update/duplicate/updateCell return actual data
- Remove non-functional Run All button from notebook editor
- Replace confirm() dialog with immediate delete + toast notification
- Remove dead notebook placeholder branch in tab-query-editor
- Remove duplicate react-markdown/remark-gfm from root package.json
* chore: lock files
* docs(notebooks): add feature docs, demo runbook, and nav entry
- SQL Notebooks feature documentation page for docs site
- Demo runbook .dpnb file for ACME SaaS health checks
- Add sql-notebooks to features navigation
* content(notebooks): add release notes, social posts, and 3 blog posts
- Release notes for v0.20.0 (SQL Notebooks)
- Social media posts (Twitter, Reddit, Dev.to)
- Blog 11: Feature announcement
- Blog 12: Storage architecture deep dive
- Blog 13: Lazy-loading Monaco in notebook cells
* content(notebooks): add Threads posts and posting strategy
4 Threads posts: launch carousel thread, technical behind-the-scenes,
runbook showcase, and conversation starter. Includes posting cadence
and format tips.
* docs(notebooks): add demo recording script
* feat(video): add release video and demo video for SQL Notebooks
- ReleaseVideo020: 24s release announcement (4 feature scenes)
- NotebookDemo: 45s feature walkthrough with animated notebook mockup
showing cells typing in, queries executing, results sliding in,
keyboard navigation, and export formats
* feat(video): add new background music for notebook videos
Screen Saver by Kevin MacLeod (CC BY 4.0) as primary track,
Equatorial Complex as alternative. Both compositions updated
to use the new track.
* fix: apply CodeRabbit auto-fixes
Fixed 5 file(s) based on 5 unresolved review comments.
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Embeds hero and supporting screenshots into the health monitor, data
masking, LISTEN/NOTIFY, and benchmark mode posts. Images live under
apps/web/public/blog/<slug>/ and are resolved via the existing MDX img
component, which wraps each in a styled figure with an alt-text caption.
All images resized to 1920px max width and stripped of metadata,
bringing the total blog asset size from ~32MB to ~7MB. Data generator
post intentionally left image-less pending screenshots.
The panel had no surface for connection health: the main process
silently auto-reconnected but the renderer never learned about it,
isConnected got stuck true, and there was no way to trigger a reconnect.
- Broadcast PgNotificationConnectionStatus over pg-notify:status with
state, retry attempt, next retry time, backoff, and last error
- Add forceReconnect() + IPC handlers (pg-notify:reconnect, get-status,
get-all-statuses) and preload bridge
- Replace boolean isConnected with a per-connection status map in the
renderer store; hydrate on init
- New PgNotificationStatusStrip: terminal-style vitals row with pulsing
state dot, pg_notify@host, channel count, live rx rate, uptime, a
30s canvas sparkline of event rate, retry countdown + progress bar,
and a Retry now button when disconnected or reconnecting
- Flash new events with a 2px emerald left border and row fade
- Drop the now-redundant Stats collapsible (live in the strip)
All motion is motion-safe gated and under 600ms.
Hover-to-peek was broken in the editable table because the masked span
had pointer-events-none, so mouse events never fired. In both tables,
Alt was only checked onMouseEnter, so pressing Alt while already hovering
did nothing.
Use onMouseMove so peek toggles when Alt is pressed/released mid-hover.
The blog page reads notes/*.mdx at build time, but notes/ lives outside
apps/web so Turbo's default in-package hashing missed it. Adding new
posts to notes/ resulted in FULL TURBO cache hits that replayed the
stale build, leaving new posts invisible on the live blog.
Declare notes/** as an extra input for @data-peek/web#build so any
change under notes/ busts the cache and triggers a real rebuild.
Covers previously unblogged features: the Connection Health Monitor
(pg_stat_activity dashboard + kill queries), the data masking toolbar,
the Postgres LISTEN/NOTIFY panel, benchmark mode with p90/p95/p99, and
the FK-aware data generator. Each post follows the existing notes/ voice,
references real code paths, and is ready for cross-posting to dev.to with
a canonical URL back to data-peek.app/blog.
https://claude.ai/code/session_018GVvk8S82Qy9VVK4eibzaW
Co-authored-by: Claude <noreply@anthropic.com>
* docs(plan): add docs site revamp design
Root-causes the slow layout transitions on docs.datapeek.dev
(Framer Motion 500ms fade, sidebar tree re-sent per nav, version
lag) and plans phased fix: triage, version bumps, MDX brittleness,
prerender, brand polish, follow-up distinctive design pass.
* docs(plan): add docs site revamp implementation plan
Phased tasks covering Framer Motion / tree-reload removal,
version bumps (Fumadocs 16.7, TanStack 1.168), remark plugins
for resilient MDX parsing, CI types:check gate, prerender, and
typography polish. Validation checklist at the end.
* perf(docs): remove page fade-in and move tree to parent route
Framer Motion wrapper added a 500ms fade on every nav and the
sidebar tree was re-sent and re-transformed per navigation. Move
the tree to a new /docs parent layout route with staleTime:Infinity
and drop the motion wrapper + CSS fade-in on main.
Navigating /docs/* now feels instant.
* chore(docs): bump fumadocs to 16.7 / 14.2 and switch to useContent
fumadocs-ui/core 16.2.1 -> 16.7.x and fumadocs-mdx 14.0.4 -> 14.2.x.
fumadocs-mdx 14.2 tightened ClientLoader typings so getComponent()
returns FC<never> by default. Switch to clientLoader.useContent()
which is the canonical Fumadocs-on-TanStack pattern anyway — cleaner
and handles Suspense internally.
* chore(docs): bump tanstack router/start to 1.168/1.167
Bumps @tanstack/react-router to ^1.168.10, @tanstack/react-start to
^1.167.16, and @tanstack/react-router-devtools to ^1.166.11. Catches
~34 minor versions of hydration, loader, scroll restoration, and
routing fixes. No source changes required - existing createFileRoute,
createServerFn, inputValidator, and createRouter APIs remain compatible.
* fix(docs): harden MDX parsing and add types:check CI gate
Add remark-gfm + remark-smartypants to fumadocs MDX config so
prose containing numeric operators, comparisons, and angle
brackets parses cleanly without author discipline. The workaround
from 60282cd (backtick-wrapping operators) is no longer strictly
needed, though we leave existing wrappers in place.
Add .github/workflows/docs-types.yml that runs pnpm --filter docs
types:check on every PR touching apps/docs. This parses every MDX
file and fails the build if anything regresses — catches the kind
of issue that hit prod in 60282cd.
* docs(plan): capture post-revamp perf baseline and defer prerender
Prerender attempted but blocked by a race between tanstack-start-
plugin-core and nitro@3.0.1-alpha.1 in the preview-server handoff
(fetches the first route before the nitro child process has bound
to its port). Runtime is fine — only the prerender crawl fails.
Documented the deferral in the baseline file.
Baseline measurements taken against the non-prerendered production
build for future regression comparisons.
* style(docs): tighten typography scale and body rhythm
Smaller h1/h2/h3 (1.875/1.25/1.0625 rem) and body line-height 1.6
match the 'dense but scannable' principle in CLAUDE.md and bring
the docs closer to Linear/Raycast density without sacrificing
readability.
* docs(plan): mark docs revamp validation checklist and note follow-ups
Code-level items verified, visual items flagged for human check.
Honest on the LCP number: 7.8s under Lighthouse mobile throttling
does not meet the 1.5s target, though TBT is 0ms and server latency
is ~20ms so perceived perf is far better than the mobile score.
Broken-internal-links check dropped from Phase 2 — noted as
follow-up.
* fix(docs): scope prose link color so landing hero CTA is readable
The global \`a { color: var(--dp-accent) }\` rule was leaking into
\`routes/index.tsx\` and overriding the landing page CTA's inline
\`text-[#0a0a0b]\` class. Because the CTA background is also
var(--dp-accent), the button text was invisible-on-itself.
Scope the rule to \`article a\` so it only styles MDX prose
content (docs pages wrap in <article> via DocsPage; landing uses
<main> via HomeLayout). Sidebar, TOC, and navbar links already
have their own scoped rules and are unaffected.
This bug was pre-existing (introduced in 04268973, 2025-11-30) but
surfaced during the docs revamp visual review.
* fix(docs): resolve type checking errors and commit routeTree.gen.ts
* fix(docs): resolve hydration crash and broken navigation
- Moved server-only `source.getPage()` calls from client-side `head()` into server-side `loader()`.
- Passed extracted metadata (title, description, breadcrumbs) to `head()` via `loaderData`.
- Relocated structured data injection to React component tree to fix hydration mismatches.
- Removed blocking third-party scripts from root route.
* chore(docs): remove playwright dep and dead getOrganizationStructuredData code
- Remove playwright from devDependencies (only used for one-off verification)
- Remove unused getOrganizationStructuredData import from __root.tsx
- Remove dead getOrganizationStructuredData function from seo.ts (zero callers)
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* Add sidebar omnibar with fuzzy search and physics-based transitions
Unified search bar below connection switcher that fuzzy-matches across
tables, columns, routines, saved queries, snippets, and query history.
Press `/` to focus. Spring-curve animations on all collapsible sections
and stagger-reveal for schema tree items. Respects prefers-reduced-motion.
* Address review: scope animations, fix cmdk uniqueness, cleanup
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
- Add Remotion release video for v0.19.0 with 5 feature scenes:
Web SQL Client, Table Editor UX, Smart Filter Bar,
Local-First Storage, and Shared UI Package
- Fix electron-builder Windows build by moving @data-peek/ui
to devDependencies (it's renderer-only, bundled by Vite)
- Fix unused onCopy prop in smart-filter-bar causing TS error
* feat(desktop): smart filter bar with type-aware operators and animated copy
Replace the old per-column filter inputs with a unified command-palette-style
filter bar. Supports global text search across all columns, column autocomplete
with type badges, type-aware operators (string/numeric/date/boolean), and
persistent filter chips with keyboard-first flow (⌘F → column → Tab → operator
→ Tab → value → Enter).
Key changes:
- Smart filter bar with chip-based filters and live result count
- Click-to-copy on cells and chips (animated checkmark draw), double-click to edit
- Inline "Apply to Query" banner when client-side filters are active
- Filter persistence store (Zustand + localStorage) per connection+table
- All animations respect prefers-reduced-motion via motion-safe: prefix
* Address review: deduplicate click-copy logic, fix filter bugs, remove dead code
- Extract useClickCopy hook shared by CopyableCell and FilterChipButton
- Extract getTypeCategory helper to deduplicate type detection logic
- Fix date comparison in gt/gte/lt/lte operators (Number coercion on dates)
- Fix between filter returning true on malformed input (now returns false)
- Replace module-level chipIdCounter with crypto.randomUUID()
- Remove unused filter-store.ts
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
This is an automated pull request generated by Vercel to help install [Speed Insights](https://vercel.com/docs/speed-insights) in your application.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: Rohith Gilla <gillarohith1@gmail.com>
# Vercel Speed Insights Installation
Successfully installed and configured Vercel Speed Insights for the data-peek webapp project.
## Changes Made
### 1. Package Installation
- Added `@vercel/speed-insights` version ^2.0.0 to dependencies in `apps/webapp/package.json`
- Updated `pnpm-lock.yaml` with the new dependency and its transitive dependencies
### 2. Component Integration
- Modified `apps/webapp/src/app/layout.tsx`:
- Imported `SpeedInsights` component from `@vercel/speed-insights/next`
- Added `<SpeedInsights />` component inside the `<body>` tag, alongside the existing `<Analytics />` component
## Implementation Details
The implementation follows the official Vercel Speed Insights quickstart documentation for Next.js App Router (v13.5+):
- Used the correct Next.js-specific import path: `@vercel/speed-insights/next`
- Placed the component in the root layout file at `app/layout.tsx`
- Added the component inside the `<body>` tag as recommended
## Framework
This project uses Next.js 16.0.7 with the App Router architecture, so the implementation uses the App Router-specific instructions from the official documentation.
## Next Steps
To enable Speed Insights:
1. Deploy the application to Vercel
2. Navigate to the Vercel dashboard
3. Select Speed Insights from the sidebar
4. Choose the project and click Enable
5. After deployment, the Speed Insights script will be automatically injected at `/_vercel/speed-insights/*`
6. Once users visit the site, performance metrics will appear in the Vercel dashboard
## Notes
- The existing `@vercel/analytics` package was already installed, so this addition complements the existing analytics setup
- The pre-existing build errors in the codebase are unrelated to this change - they stem from missing dependencies in the shared `packages/ui` package
- The SpeedInsights component is zero-bundle-size on the client and only loads the tracking script when needed
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Migrated page.tsx, tab-container, command-palette, edit-toolbar,
results-table, schema-table-item, and use-sync-url from useQueryStore
to useQueryTabs. Ephemeral execution state (results, errors, executing)
now lives in React state. Query history auto-records to Dexie on execute.