## Summary
Fixes
[FE-3060](https://linear.app/supabase/issue/FE-3060/modshiftc-modshiftm-shortcuts-suppressed-when-a-table-editor-cell-is).
`Mod+Shift+C` (Copy as CSV) and `Mod+Shift+M` (Copy as Markdown) — and
any other Meta/Ctrl/Escape shortcut registered via `useShortcut` without
an explicit `ignoreInputs` — stopped firing when focus landed on a
`react-data-grid` cell in the table editor (or any other
input/contenteditable).
## Fix
In `apps/studio/state/shortcuts/useShortcut.tsx`, only include
`ignoreInputs` in the options object when it's actually set, so
TanStack's register-time default sticks across re-renders.
Updated the `ignoreInputs resolution` test to assert that the key is
omitted (rather than passed as `undefined`) when neither caller nor
registry set it.
## Test plan
- [x] SQL editor results: `Cmd+Shift+C`, `Cmd+Shift+M`, `Cmd+Shift+J`,
`Cmd+Shift+D` still fire
- [x] `Mod+ArrowUp` / `Mod+ArrowDown` / `Mod+ArrowLeft` /
`Mod+ArrowRight` inside a focused cell editor still blocked (registry
sets `ignoreInputs: true`)
- [x] Unit tests: `pnpm vitest run state/shortcuts/useShortcut.test.tsx`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed keyboard shortcut handling to properly respect the hotkey
library's default configuration values when custom options are not
explicitly specified.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Closes
[FE-3056](https://linear.app/supabase/issue/FE-3056/add-unit-tests-for-new-shortcut-primitives).
Backfills unit coverage for the shortcut primitives added in the recent
keyboard-shortcut overhaul — these shipped with no tests.
- **`state/shortcuts/formatShortcut.test.ts`** (16 tests) —
`hotkeyToKeys`: `Mod → Meta` mapping (case-sensitive, substring-safe),
single/multi-modifier combos, named keys, punctuation, edge cases.
- **`state/shortcuts/useShortcut.test.tsx`** (26 tests) — mocks
`useHotkeySequence`, `useRegisterCommands`, and `useIsShortcutEnabled`
to unit-test: sequence/callback wiring (single-step + multi-step
G-chords), full option-resolution priority (caller → registry →
fallback) for `enabled` / `timeout` / `ignoreInputs`, global-preference
AND gating, command-menu registration across all four enable
permutations, stable action identity, stale-closure protection via
`useLatest`, and badge rendering with/without the "then" separator.
- **`components/ui/Shortcut.test.tsx`** (12 tests) — mocks `useShortcut`
and `ShortcutTooltip` to verify prop forwarding (including rerender
behavior), tooltip positioning props, unset-prop hygiene, and the
`asChild` pass-through contract (clicks on the child do not fire
`onTrigger`).
54 tests total, all passing.
## Test plan
- [x] `pnpm --filter studio test state/shortcuts/formatShortcut.test.ts
state/shortcuts/useShortcut.test.tsx components/ui/Shortcut.test.tsx`
- [x] `tsc --noEmit` clean across the three test files
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Added comprehensive test coverage for the Shortcut component,
verifying rendering, hook integration, and tooltip behavior.
* Added test suite for hotkey key formatting, covering plain keys, named
keys, modifiers, and edge cases.
* Added test suite for the useShortcut hook, validating hotkey
sequences, enablement logic, command menu integration, and callback
handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Adds `<Shortcut>` component: binds a registered shortcut + renders a
Linear-style hover tooltip (label + keybind pills) in one declaration
- Adds `<ShortcutTooltip>` as the lower-level primitive for cases where
binding lives elsewhere
- Registers 13 G-chord navigation shortcuts (`G H` / `G T` / `G S` / `G
D` / `G A` / `G B` / `G F` / `G R` / `G V` / `G O` / `G L` / `G I` / `G
,`)
- Wires shortcuts into `SideBarNavLink` — binding + dynamic-delay
tooltip (0ms collapsed, 1000ms expanded) replaces the old label-only
collapsed tooltip
Closes
[FE-3048](https://linear.app/supabase/issue/FE-3048/create-navigation-shortcuts).
## Test plan
- [x] Hover each main sidebar nav item with sidebar expanded — tooltip
appears after delay with label + shortcut pills
- [x] Collapse sidebar — tooltip appears instantly on hover
- [x] Press `G` then a registered letter anywhere outside text inputs —
navigates to that screen
- [x] Press `G` inside a text input — no navigation fires
- [x] Disabled nav items (project inactive) — no shortcut fires, no
tooltip anomaly
- [x] Feature-gated routes (auth/storage/realtime off) — shortcut is
gone with the route
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Global keyboard shortcuts added for navigating major app sections
(home, editors, database, auth, storage, functions, realtime, advisors,
observability, logs, integrations, settings).
* Navigation items display their keybinds in hover tooltips and can be
triggered via those shortcuts.
* Tooltip timing adapts to sidebar state (immediate when collapsed,
delayed when expanded).
* Shortcut-aware tooltip display now shows multi-step key sequences
clearly.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Follow-up to #45099 — migrates the final legacy hotkey hook
(`useKeyboardShortcuts` in
`apps/studio/components/grid/components/common/Hooks.tsx`) to
`useShortcut`, backed by `SHORTCUT_DEFINITIONS`.
- Adds 4 registry entries (`TABLE_EDITOR_JUMP_FIRST_ROW` / `_LAST_ROW` /
`_FIRST_COL` / `_LAST_COL`), all `showInSettings: false` so they stay
non-configurable (same as today).
- Adds `ignoreInputs` to `ShortcutOptions` and threads it through
`useShortcut` → `useHotkeySequence`. Replaces the legacy
`whitelistNodes: ['INPUT', 'TEXTAREA', 'SELECT']` with the built-in
TanStack option, which also covers `contenteditable`.
- Drops the `navigator.appVersion` macOS/Windows detection in
`Shortcuts.tsx` (`Mod` resolves this automatically) and the manual
`event.stopPropagation()` calls (TanStack's default is `stopPropagation:
true`).
- Deletes `Hooks.tsx` — no remaining consumers.
Closes FE-3049.
## Why `ignoreInputs: true` on these entries
`Mod+Arrow*` is a Ctrl/Meta combo. TanStack's default for Ctrl/Meta
combos is `ignoreInputs: false`, which would fire the shortcut even when
focus is in a text input — not what we want. Setting `ignoreInputs:
true` in the registry preserves the legacy whitelist behavior.
## Test plan
All shortcuts should still fire with **Cmd** (macOS) / **Ctrl**
(Win/Linux). Test surface: **Table Editor** → open any table with rows
and multiple columns.
**Grid navigation (with a cell selected — click a cell first)**
- [x] `Cmd+ArrowUp` jumps selection to row 0 in the same column
- [x] `Cmd+ArrowDown` jumps selection to the last row in the same column
- [x] `Cmd+ArrowLeft` jumps selection to the first non-frozen column in
the same row
- [x] `Cmd+ArrowRight` jumps selection to the last column in the same
row (not the trailing "add column" cell)
**Whitelist regression (most important — the `ignoreInputs` check)**
- [x] Open the **Filter** popover on a table → put focus in the filter
value `<input>` → type with arrow keys / use `Cmd+ArrowLeft/Right` for
word-jump → cursor moves in the input, grid selection does **not** jump
- [x] Same for a `<textarea>` (e.g. row editor → a text column with a
textarea) — `Cmd+ArrowUp/Down` should not hijack focus away from the
textarea
- [x] Same for a `<select>` (e.g. row editor → enum / boolean column) —
arrow keys behave normally
- [x] Editing a cell value in-place (double-click a cell to enter edit
mode) — arrow keys navigate the text, don't jump the grid
**Platform check**
- [x] On macOS, the shortcuts fire with `Cmd` (not `Ctrl`)
- [x] On Windows/Linux, they fire with `Ctrl` (not `Cmd`) — `Mod`
resolution
- [x] None of the new entries appear in Account → Preferences → Keyboard
shortcuts (all `showInSettings: false`)
**Regression checks**
- [x] `pnpm --filter=studio typecheck` passes (verified locally)
- [x] Existing shortcuts from #45099 (`Cmd+K`, `Cmd+I`, `Cmd+S` in op
queue, results copy, etc.) still work unchanged
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added four keyboard shortcuts for table navigation: jump to first/last
row and first/last column using Mod+Arrow keys.
* Added a shortcut option to prevent triggers when focus is in input
fields.
* **Bug Fixes**
* Improved keyboard shortcut handling for more consistent behavior
across platforms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Migrates all 11 `useHotKey` call sites across 9 files to
`useShortcut`, backed by `SHORTCUT_DEFINITIONS` in
`state/shortcuts/registry.ts`.
- Adds 10 new registry entries (all `showInSettings: false` to keep
behavior identical to today — these were not previously
user-configurable).
- Deletes `apps/studio/hooks/ui/useHotKey.ts`.
- Simplifies `ActionBar.handleSave` — the legacy hook passed a
`KeyboardEvent` the callback used for `preventDefault`/`stopPropagation`
and a textarea-plain-Enter guard; all of that is redundant under
`useShortcut` (TanStack handles default/propagation; `Mod+Enter` never
fires on plain Enter).
- Removes a stale commented-out `useHotKey` reference in
`DataTableFilterCommand.tsx`.
Part of FE-3025 (legacy hotkey hook cleanup). `useKeyboardShortcuts` in
`grid/components/common/Hooks.tsx` will be migrated in a follow-up.
## Test plan
All shortcuts should still fire with **Cmd** (macOS) / **Ctrl**
(Win/Linux).
**Table Editor — operation queue** (requires pending unsaved edits on a
row)
- [x] `Cmd+S` saves pending edits
- [x] `Cmd+.` toggles the operation queue side panel
- [x] `Cmd+Z` undoes the latest edit and re-fetches the affected table
rows
- [x] With no pending edits, none of the above fire (gated by
`isEnabled`)
**Table Editor — side panel editor forms** (row, table, column, policy,
etc.)
- [x] `Cmd+Enter` submits the form when the panel is visible
- [x] Does not submit if the form is disabled/loading or the panel is
hidden
**Unified Logs — data table**
- [x] `Cmd+B` toggles the filter controls sidebar (desktop)
- [x] `Cmd+B` opens the filter drawer (mobile, `<sm` breakpoint)
- [x] `Cmd+Esc` resets active column filters (reset button visible)
- [x] `Cmd+U` resets column order + visibility
- [x] `Cmd+J` toggles live mode
**Unified Logs — reset focus**
- [x] `Cmd+.` blurs the currently focused element / resets focus to body
**AI Assistant panel**
- [x] While editing a message, `Cmd+Esc` cancels the edit
**Regression checks**
- [x] `pnpm --filter=studio typecheck` passes (verified locally)
- [x] None of the new shortcut entries appear in Account → Preferences →
Keyboard shortcuts (all `showInSettings: false`)
- [x] Existing shortcuts (`Cmd+K`, `Cmd+I`, `Cmd+E`, results
copy/download) still work unchanged
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Refactor
* Implemented a centralized keyboard shortcut registry system for
managing shortcuts consistently across the application
* Updated multiple UI components throughout the interface to use the new
shortcut management system
* All existing keyboard shortcuts continue to function without any
changes in behavior or user experience
## Chores
* Removed legacy keyboard shortcut hook implementation
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What kind of change does this PR introduce?
Feature. Resolves DEPR-430.
## What is the current behaviour?
The homepage Advisor summary, shared Advisor panel, and top-nav Advisor
indicator only surface lints and notifications. Banned IPs are not
represented as dismissible Advisor items, so network bans are easy to
miss unless a user visits Database Settings directly.
The `public bucket allows listing` warning is no longer part of this PR.
That warning will move to a follow-up Splinter `WARN` lint so it can
flow through the standard lint surfaces instead of a bespoke Studio
signal path.
## What is the new behaviour?
- adds a new Advisor `signal` source for banned IPs on the platform
homepage, in the shared Advisor panel, and in the top-nav Advisor
indicator
- keeps dismissals client-side only for now, scoped by project and exact
IP fingerprint
- keeps banned IP signals at `warning` severity because they still
indicate suspicious traffic and remain actionable if a user wants to
review or remove a ban
- leaves `/project/[ref]/advisors/security` as follow-up work because
that surface is still lint-native, and banned IPs are management-plane
signals rather than Splinter lints
| After |
| --- |
| <img width="1728" height="997" alt="Mallet Toolshed
Supabase-65A60B4A-107E-4D79-B9A8-23F754BEAB08"
src="https://github.com/user-attachments/assets/c08ecbbb-c302-43bd-81bb-6ba7eb18b7b3"
/> |
## Reviewer testing notes
1. Use a throwaway project.
2. Get the database connection string for that project.
3. Attempt to connect with the wrong password 3-4 times until you hit an
`ECONNREFUSED`-style error, which should mean your IP has been banned.
4. Refresh Studio and confirm the project overview shows the new `Banned
IP address` signal.
5. Open the Advisor Center and confirm:
- the top-nav Advisor dot turns warning yellow
- the signal detail shows `Entity`, `Issue`, and `Resolve`
- `Edit network bans`, `Dismiss`, and `Learn more` are present
6. Open Database Settings > Network bans and confirm your banned IP
appears there and can be unbanned.
7. Note that `/project/[ref]/advisors/security` will not show this item.
That page is still lint-only, and this banned IP work is a short-term
client-side signal rather than a true lint.
Longer term, we likely want a more durable event model here so banned
IPs can power notifications, webhooks, emails, and other project-level
alerts.
---------
Co-authored-by: kemal <hello@kemal.earth>
Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Closes
[FE-3021](https://linear.app/supabase/issue/FE-3021/hide-shortcut-in-settings-option-for-new-api).
## Summary
- Adds an optional `showInSettings` field to `ShortcutDefinition`
(defaults to `true`).
- `HotkeySettings` filters out entries where `showInSettings === false`
before rendering the Account → Preferences → Keyboard shortcuts list.
- No registry entries are flipped in this PR — opt-in per shortcut as
needed.
## Test plan
- [x] Confirm all existing shortcuts still appear under Account →
Preferences → Keyboard shortcuts.
- [x] Temporarily set `showInSettings: false` on one entry and verify it
disappears from the list.
- [x] `pnpm --filter studio exec tsc --noEmit` passes.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Keyboard shortcuts can now be selectively hidden from the Account
preferences settings based on configuration.
* **Refactor**
* Updated keyboard shortcut filtering logic to respect visibility
settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Cleanup shortcuts with new hooks
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Centralized keyboard shortcut system for consistent shortcut behavior
across the app and moved preference toggles to a unified registry.
* **New Features**
* Added explicit shortcuts for Command Menu, AI Assistant, Inline
Editor, and result copy/download actions.
* Hotkey preferences UI now renders dynamically from the centralized
shortcut list.
* **Tests**
* Test helpers updated to include the command menu provider for accurate
shortcut behavior in tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
- Brand new hook APIs for registering shortcuts using tanstack hotkeys
- Support for command menu injection when shortcut is added
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Centralized keyboard shortcuts system with per‑shortcut registration
and per‑user enable/disable preferences stored locally
* Added a "Copy results as Markdown" shortcut (Mod+Shift+M)
* Shortcuts can be surfaced in the Command Menu with a visual shortcut
badge for discoverability
* **Documentation**
* Legacy keyboard shortcut hooks marked as deprecated and documentation
updated to point to the new shortcut API
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We currently have 3 different libraries for drag & drop, two of which
are not actively maintained anymore.
## Solution
Migrate all usage of the two unmaintained libraries to DndKit.
This PR focuses on using DndKit instead of `react-dnd` for column
reordering in the table editor
## Screencast
https://github.com/user-attachments/assets/54fb36f4-5671-42e2-9698-2ae928a69f55
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Column drag-and-drop rebuilt with a live drag preview and improved
pointer/keyboard handling
* **Improvements**
* More reliable column reordering with refined move/freeze/unfreeze
behavior and stable index recomputation
* Standardized column type/format display and simplified grid rendering
* **Accessibility**
* Added accessible labeling for column actions controls
* **Tests**
* End-to-end locator updated to target the column actions button
deterministically
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* **Refactor**
* Updated internal module import paths to use standardized alias
conventions across the codebase.
* Reorganized import statement ordering for improved code consistency.
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Refactor
## What is the current behavior?
Storage explorer preferences (`view`, `sortBy`, `sortByOrder`,
`sortBucket`) are managed inline within the Valtio proxy state in
`storage-explorer.tsx`, which reads/writes localStorage directly.
## What is the new behavior?
Preferences are extracted into a dedicated `useStoragePreference` hook
backed by `useLocalStorage`. A companion `getStoragePreference` function
allows the Valtio state to read sort options imperatively for API calls
without holding preference data itself. Consumers import the hook
directly instead of reading preferences from the snapshot.
## Additional context
No behavioral or visual changes — localStorage key and data shape are
unchanged.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Storage view and sorting preferences now persist per project and drive
the explorer UI.
* Changing view or sort preferences refreshes folder contents and clears
the open file preview.
* **Chores**
* Centralized preference handling for consistent behavior across the
storage explorer.
* **Tests**
* Updated tests to exercise the new preference-backed behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
The `connectSection` A/B experiment concluded as a true null (no effect
on activation or any downstream metric after 13 days at 50/50, ~153K
mature orgs). Saxon decided to ship the Connect section as the permanent
experience. This PR removes the Getting Started control variant, the old
Connect modal, all experiment flag gating, and related telemetry types.
## Changes
- Delete `GettingStarted/` directory (5 files: section component, types,
utils, progress hook)
- Delete old `Connect.tsx` dialog modal (replaced by ConnectSheet)
- Remove `connectSection` PostHog flag reads from `Home.tsx` and
`LayoutHeader.tsx`
- Remove `getSectionVisibility()` experiment logic and
`ConnectSectionVariant` type
- Remove `getting-started` from `DEFAULT_SECTION_ORDER`
- Always render `<ConnectSheet />` in header (no more conditional with
old `<Connect />` modal)
- Remove `variant` prop from `ConnectSection` component
- Remove 4 getting-started telemetry event interfaces from
`telemetry-constants.ts`
- Update `mergeSectionOrder` tests to reflect new section order
## Testing
Tested on Vercel preview:
- [x] Project homepage shows Connect section for new projects (< 10 days
old)
- [x] Connect section hidden for mature projects (> 10 days old)
- [x] Header Connect button opens ConnectSheet (not old modal)
- [x] Connect tiles open ConnectSheet with correct tab
- [x] Section drag-and-drop still works without getting-started in the
order
- [x] Existing users with `getting-started` in localStorage order don't
break (mergeSectionOrder strips it)
## Linear
- fixes GROWTH-730
---------
Co-authored-by: Alaister Young <alaister@users.noreply.github.com>
## Problem
When scrolling down in a column that has more than 200 items to trigger
its lazy loading, while other columns are displayed and the targeted
column isn't the last one, it doesn't load its items.
Fixes#43799
## Solution
- Don't rely on the storage state for opened folders for the lazy
loading
- Add the item path information to the column and use it to define the
API request path
## How to test
- create a bucket
- create a folder and upload more than 200 items in it
- in this folder, create a sub folder and upload more than 200 items in
it (make sure its name position it _before_ the files)
- refresh the page
- without scrolling the first column, select the subfolder
- now scroll down on the first column past the last of its items and
verify it loads more items
- do the same on the sub folder column
To easily create many files to upload, use the following commands:
For root folder:
```sh
for i in {0..300}
do
echo hello >"root_$(printf "%03d" "$i").txt"
done
```
For sub folder:
```sh
for i in {0..300}
do
echo hello >"sub_$(printf "%03d" "$i").txt"
done
```
We're exploring support for newer models like
[gpt-5.4-nano](https://openai.com/index/introducing-gpt-5-4-mini-and-nano/)
in Assistant. This model doesn't support the `'minimal'` reasoning
effort level we use for gpt-5-mini which leads to vague errors.
<img width="595" height="263" alt="CleanShot 2026-03-18 at 17 13 05@2x"
src="https://github.com/user-attachments/assets/cf7c2370-322d-4a8a-be55-23e680db0aa0"
/>
Also, we've [previously
discussed](https://supabase.slack.com/archives/C0161K73J1J/p1771544464850199?thread_ts=1771493920.775699&cid=C0161K73J1J)
that reasoning adds unnecessary latency to otherwise simple AI
completion endpoints like `title-v2`. We want more control of reasoning
level independent of model/endpoint.
This PR aims to solve both problems by:
- making reasoning effort configurable on a per-request basis
- adding compile-time guardrails to prevent selecting an incompatible
reasoning level for models
- adding a `DEFAULT_COMPLETION_MODEL` with minimal reasoning that we can
update with newer models that support disabling reasoning (independent
of Assistant chat model reasoning)
Other improvements to our model config logic:
- Fixes bug in `onboarding/design.ts` and `assistant.eval.ts` where
`providerOptions` was being dropped
- `getModel()` now returns a bundled `modelParams` object (spread into
AI SDK calls) so `providerOptions` can't be accidentally omitted (this
[has happened
before](https://supabase.slack.com/archives/C0161K73J1J/p1771518443534309?thread_ts=1771493920.775699&cid=C0161K73J1J))
- Introduces an `ASSISTANT_MODELS` registry as a single source of truth
for assistant model config, eliminating hardcoded model IDs across the
codebase
- Aligns free/pro model conditional logic with `assistant.advance_model`
entitlement naming conventions instead of the `isLimited` pattern
- Adds `console.error` logging of Assistant stream errors so we can
interpret reasoning effort compatibility errors in the future (instead
of just opaque "Sorry, I'm having trouble responding right now" card)
- Removes unnecessary type casts and generally making the model config
logic stricter
- Removes pre-existing dead code: `anthropic` provider variant in
`GetModelParams` / `PROVIDERS` registry that was never implemented in
`getModel()`
Now if you try to select an unsupported reasoning level you get a type
error:
<img width="1306" height="320" alt="CleanShot 2026-03-20 at 14 37 24@2x"
src="https://github.com/user-attachments/assets/a6ac234b-5ea5-4d81-8e01-ac4be34a0800"
/>
And if for some reason an invalid reasoning level slips through, you now
get a server-side error surfacing the issue:
<img width="1268" height="204" alt="CleanShot 2026-03-20 at 14 58 14@2x"
src="https://github.com/user-attachments/assets/aadc1b7a-9495-475f-9741-39979bd27cd7"
/>
I've tested gpt-5 and gpt-5-mini are still working on the staging
preview and verified the models were selected properly in Braintrust
logs. Both models are available on my Pro test account, and my Free test
account shows the Pro upgrade CTA.
Closes AI-446
Closes AI-551
## What kind of change does this PR introduce?
Bug fix that resolves DEPR-414.
## What is the current behavior?
Browser titles in the table/SQL editors can keep showing an old entity
name after a rename.
## What is the new behavior?
- `EditorBaseLayout` now prefers the live tab label when composing the
browser title entity, so existing stale tab metadata no longer wins.
- Updating a tab label now also syncs the persisted `metadata.name`, so
renamed entities recover cleanly on reload instead of carrying stale
names in local storage.
- Adds a regression test covering the stale-metadata case in the editor
layout.
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## What kind of change does this PR introduce?
Bug fix.
## What is the current behavior?
The `Recent items` list shown in the table editor empty-state can keep
showing an old label after a table or SQL snippet is renamed.
That UI is mounted from:
- `/project/[ref]/editor`
- `/project/[ref]/editor/new`
## What is the new behavior?
- Re-adding an existing recent item now refreshes its label and metadata
instead of only bumping the timestamp.
- Updating an open tab label now also updates the matching recent item,
so rename flows stay aligned with the recent-items list.
- The fix is applied in the shared tabs store, so table and SQL editor
tab state stay consistent even though the visible `Recent items` UI
currently appears in the table editor empty-state.
- Adds a small store-level regression test for both cases.
| Before | After |
| --- | --- |
| <img width="1024" height="563" alt="test Table Editor Mallet Toolshed
Supabase-DA49998A-FE09-4197-8EE7-5D5366FABDC7"
src="https://github.com/user-attachments/assets/d0475437-4486-4581-82f8-a84b97b08250"
/> | <img width="1024" height="563" alt="test Table Editor Mallet
Toolshed Supabase-8F2B6CC9-0721-4348-A094-EE94D6919B08"
src="https://github.com/user-attachments/assets/f055be35-4373-4b1b-a2e1-ffe59f12c177"
/> |
(working with @charislam @awaseem on this one)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
Per
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md):
- ✅ `pnpm --filter studio build`
- ✅ `pnpm test:prettier`
- ✅ `pnpm format`
## What kind of change does this PR introduce?
Instruments `studio` app's table creation flow with Sentry.
## What is the current behavior?
The table creation flow isn't instrumented in detail, which means we
have less visibility into understanding performance problems or errors
within this specific flow.
## What is the new behavior?
The table creation flow is instrumented in detail. This instrumentation
allows for Sentry dashboards like this one (created based on locally
generated Supabase data), to help monitor anything going wrong with this
critical flow:
<img width="1915" height="1131" alt="image"
src="https://github.com/user-attachments/assets/e2c5380e-7b00-41c1-9109-3ee4e47ff63b"
/>
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## Summary
Re-ports PR #43119 against the current `ProjectHome` codebase (the
original PR targeted `HomeNew/` which was removed during the `homeNew`
graduation in #43437). Also unifies the `connectSheet` and
`connectSection` feature flags into a single `connectSection` flag — the
`connectSheet` flag is removed entirely, so both the ConnectSheet
(header) and ConnectSection (homepage row) are controlled by one
experiment.
- Adds `connectSection` PostHog experiment flag that controls two
things:
1. Swaps the Getting Started section for a Connect section on the
project homepage for new projects (< 10 days old)
2. Swaps the legacy Connect dialog for the new ConnectSheet panel in the
header
- **Control** (`getting-started`): existing Getting Started section +
legacy Connect dialog in header
- **Treatment** (`connect`): new 4-tile Connect section + ConnectSheet
in header
- `undefined` (loading): neither section renders, avoiding flash
- Tiles filtered by the same `useIsFeatureEnabled` flags as ConnectSheet
(`show_app_frameworks`, `show_mobile_frameworks`, `show_orms`)
- Connect tile clicks tracked via `home_connect_action_clicked`; section
render tracked via `home_connect_section_exposed`; sheet opens tracked
via `connect_sheet_opened` with source attribution (`header_button` or
`connect_section`)
## Changes
- `packages/common/telemetry-constants.ts` — new
`home_connect_section_exposed`, `home_connect_action_clicked`, and
`connect_sheet_opened` event types
- `ConnectSheet/ConnectSheet.tsx` — read `connectTab` query param and
sync to active mode on open; `handleModeChange` keeps param in sync on
tab switch; fire `connect_sheet_opened` event with source attribution on
open
- `ConnectButton/ConnectButton.tsx` — set `connectSource=header_button`
query param on click
- `ProjectHome/ConnectSection.tsx` — new component (4-tile connect
card); set `connectSource=connect_section` on tile click
- `ProjectHome/Home.tsx` — experiment flag wiring
- `LayoutHeader/LayoutHeader.tsx` — read `connectSection` flag instead
of `connectSheet` to toggle ConnectSheet vs legacy Connect dialog
## Test plan
To test on the Vercel preview, set `connectSection=connect` to 100% in
PostHog (or override via cookie `ph_override_connectSection=connect`).
No separate `connectSheet` flag is needed — `connectSection` controls
both features.
- [x] Treatment (`connect` variant) — "Get connected" section renders on
new project, Getting Started hidden
- [x] Control (`getting-started`) — Getting Started renders, Connect
section hidden
- [x] Mature project (> 10 days) — neither section regardless of flag
- [x] Clicking each tile opens ConnectSheet on the correct tab
(Framework / Direct / ORM / MCP)
- [x] Switching tabs inside sheet updates `connectTab` URL param
- [x] Closing sheet clears `connectTab` param
- [x] Direct URL deep-link (`?showConnect=true&connectTab=orm`) opens
sheet on correct tab
- [x] Dark mode — background gradient renders correctly
- [x] Light mode — background switches to light gradient
- [x] Responsive layout — 4 cols (xl), 2×2 (md), stacked (mobile)
- [x] Telemetry — `home_connect_section_exposed` fires once on load;
`home_connect_action_clicked` fires with correct `mode`
- [x] Treatment — header Connect button opens ConnectSheet (not legacy
Connect dialog)
- [x] Control — header Connect button opens legacy Connect dialog (not
ConnectSheet)
- [x] Telemetry — clicking a ConnectSection tile fires
`connect_sheet_opened` with `source: 'connect_section'`
- [x] Telemetry — clicking header Connect button fires
`connect_sheet_opened` with `source: 'header_button'`
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
Bug fix
## What is the current behavior?
Read-only users cannot download files because the download feature
requires minting a temporary API key, which is properly blocked for
read-only users.
## What is the new behavior?
Instead of using temporary API keys, we now create signed URLs for the
files to be downloaded. We batch-create signed URLs for an entire
folder's worth of files, requiring only a single management API call,
then use those signed URLs to download the files. This allows read-only
users to download files without needing elevated permissions.
## Additional context
Resolves FE-2737
## Context
Taking a slightly different approach to [this
PR](https://github.com/supabase/supabase/pull/43370)
Original problem was that if you opened some folders while in a bucket
and then switched to a different bucket, the folder UI will persists
(folders from Bucket A will render when landing on Bucket B)
## Changes involved
- Shift `StorageExplorerStateContextProvider` into `[bucketId].tsx]`
instead of `ProjectContext`
- The valtio store here only applies for the storage explorer so having
it so high in the project's context was unnecessary
- This also just implies that the valtio store will automatically reset
whenever the bucket changes
- Simplify storage explorer valtio store by initializing the store with
the bucket
- We'll initialize the selected bucket with the store now (Same as
previous PR)
- Removes unnecessary `setSelectedBucket` method which required a
separate `useEffect` in `StorageExplorer.tsx`
## To test
- [ ] Verify that the original is resolved
- [ ] General smoke test of the storage explorer - i've also re-added
the e2e test that Gildas wrote up in his PR
## Problem
When navigating between buckets after having selected a folder, the
storage view shows the previous folder content.
## Solution
Set the selected bucket before navigating to it, preventing a race
condition with Valtio updates and the effect that loads the bucket
content.
## How to test
1. Create 2 buckets
2. In one of them, create a folder and upload some files
3. Go back to the bucket list
4. Open the other bucket
Results:
- It should not show the previous bucket content anymore
- It should not show an empty 2nd column either
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Context
Follow up from https://github.com/supabase/supabase/pull/43329, but
mutually exclusive
Just cleaning up feature flags that have been toggled on for all users
and unchanged for the past 2 months
- edgefunctionreport
- storagereport
- realtimeReport
- postgrestreport
- authreportv2
- newEdgeFunctionOverviewCharts
- apiReportCountries (Already not used)
- SentryLogDrain
- reportGranularityV2
- storageAnalyticsVector
- ShowIndexAdvisorOnTableEditor
## Context
Main fix is to adjust the new home page + connect dialog (and connect
sheet) to render the project's custom domain if available
<img width="471" height="255" alt="image"
src="https://github.com/user-attachments/assets/3a208b2e-bdeb-43f5-a2e7-3495881dbaaa"
/>
<img width="1065" height="233" alt="image"
src="https://github.com/user-attachments/assets/2a7b8f81-8c0b-4803-bf0a-fc16a2f1e0e1"
/>
## Changes involved
- Created a `useProjectApiUrl` hook that will return the API URL
depending if custom domains is available, otherwise default to default
project API URL
- Refactored all the other places that were manually deriving the
project's endpoint
- Storage Explorer -> copy URL
- Edge Functions
- Integrations -> Data API + API Docs
- Auth Providers -> Callback URL
- Also updated the copy CTA for the addons page
- Instead of just "Change xxx", make it a bit more actionable
- For add ons with binary states (Custom domains, IPv4)
- If not enabled yet, "Enable xxx", otherwise "Toggle xxx"
- For PITR
- If not enabled yet, "Enable PITR", otherwise "Change recovery
duration"
- Also added "Edit custom domain" CTA if enabled
<img width="1144" height="518" alt="image"
src="https://github.com/user-attachments/assets/4f152ea5-0cc7-412c-95e8-ad5bb37c19c3"
/>
## To test
- [ ] Verify that for a project with custom domain set up, all the
affected UI mentioned in the above section look correct
Refactor
## What is the current behavior?
Many utility functions are in the Valtio object which is overly large
and complex.
## What is the new behavior?
Some utility functions are moved out and tested. No behaviour has been
changed, they've just been moved with any necessary changes to
arguments.
This pull request refactors how the `TabsStateContextProvider` receives
the project reference and updates related imports for consistency and
maintainability. The main change is to pass `projectRef` explicitly as a
prop instead of fetching it internally, which improves context control
and makes the component easier to test and reuse. Additionally, the PR
updates import paths to use absolute aliases and removes an unused
function.
This fixes an issue which you can replicate by:
1. Go to SQL editor
2. Open any snippet
3. Delete the local storage `supabase_studio_tabs_{project ref}`
4. Refresh the page while still the snippet is open
This will make the snippet to enter in a ghost state where the tab name
is not visible but you see the content.
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Context
Renaming folders on the Storage Explorer has a tendency to be flaky as
we're using the `POST /objects/move` storage API to move files to the
renamed folder which handles one file per request.
For a big folder (e.g 100+ files), users will easily hit rate limits and
run into 429s with the API, in which the current behaviour just shows
toast errors as the error handler, leaving an odd state upon running
through every file in the folder where some files are in the old folder,
and others in the new one
## Changes involved
Main solution is to implement an automatic retry logic for
`renameFolder`, but changes involved are:
- Remove batching logic for renaming folders (Which fires `n` requests
per batch)
- The batch logic was negligible anyways since our batch size was only 2
😅
- Instead we now handle moving of files sequentially
- If a file runs into an error during the `POST` request, retry the
request after `n` seconds
- If the error was a 429, retry after 60 seconds, otherwise just 5
seconds
- Will attempt the request for a total of 3 times
- Toast progress description will also be updated to show the message
(timer will also count down to keep the UI interactive and not look
stuck)
<img width="362" height="98" alt="image"
src="https://github.com/user-attachments/assets/52ba685a-2f35-42f1-8fcf-98351184fd56"
/>
- After the whole process is completed, if any file ran into an error,
toast description will add a CTA to retry the rename
## Demo
https://github.com/user-attachments/assets/d65b3c22-f9f8-4984-9521-6fc83a69f82e
## To test
Have a folder in your project's storage bucket with 100+ files (can
stress test with nested folders)
- [ ] Verify that you can rename the folder, and the dashboard
automatically handles errors
This pull request standardizes the usage of props and value types for
the `ResizablePanelGroup` and `ResizablePanel` components across
multiple files in the codebase. Specifically, it replaces the deprecated
`direction` prop with `orientation`, and updates numeric prop values
(such as `defaultSize`, `minSize`, and `maxSize`) to be passed as
strings. This ensures consistency with the updated component API and
improves type safety.
**Component API Updates:**
* Replaced the `direction` prop with `orientation` for all usages of
`ResizablePanelGroup`
* Updated all `ResizablePanel` props (`defaultSize`, `minSize`,
`maxSize`) to be passed as strings instead of numbers, ensuring
compatibility with the latest API requirements.
* Removed deprecated or unnecessary props such as `order` from
`ResizablePanel` components, and ensured all size-related props are
consistently formatted as strings.
- EditorPanel can now load, save, and rename SQL snippets inline
- New SaveSnippetDialog component for saving snippets with AI-generated
titles
- EditorPanel state tracks active snippet ID and pending reset
- EditQueryButton opens the inline editor panel instead of navigating to
SQL editor page
- AIEditor exposes onMount callback for editor instance access
- SnippetDropdown label updated to "Create snippet"
## TO TEST
### Normal CRUD
- open inline SQL Editor
- try creating a new snippet
- try editing an existing snippet
### Homepage V2 Report
- Try adding a new block → create snippet
- create the snippet in inline sql editor
- select the snippet in the report block section
This pull request refactors and improves error handling in the
`createStorageExplorerState` function within
`apps/studio/state/storage-explorer.tsx`. The changes make the switch
statement more robust and readable by introducing block scoping for each
case and handling additional error scenarios with more specific
messages.
* Refactored the switch statement to use block scoping (`{}`) for each
case, improving readability and preventing variable leakage between
cases.
* Enhanced the handling of HTTP 400 errors by checking the response body
for specific error messages, and displaying more precise error toasts
for "Invalid key" and "Invalid Compact JWS" cases.
* Added a default case to the switch statement to catch and display any
other error messages not explicitly handled, ensuring users receive
feedback for unexpected errors.
Enables Braintrust tracing for AI Assistant chats to support debugging
and future online evals.
**Code Changes**
- Wraps `generateAssistantResponse` in a Braintrust `traced()` span,
logging the user's latest message as input along with metadata
(`chatId`, `chatName`, `projectRef`, `userId`, `orgId`, `planId`, etc.)
- Threads JWT claims from `apiWrapper` → handler to log `userId` in
Braintrust without an extra API call (+ expanded `apiWrapper` tests)
- Threads `orgId` and `planId` from `getOrgAIDetails` to log in
Braintrust
**Infrastructure Changes**
- Created a "Vercel" service account in Braintrust
- Added `BRAINTRUST_API_KEY` and `BRAINTRUST_PROJECT_ID` env vars to the
studio-staging project in Vercel using a service token for the above
service account
- Added an "Overview" view to the Logs tab in the Braintrust Assistant
project to surface the new metadata
**Precautions**
- HIPAA sensitive projects are excluded from logging (see
https://github.com/supabase/supabase/pull/42787 for the detection logic)
- Production is temporarily excluded from logging until we're confident
in the setup
**Testing steps**
- Chat with the AI Assistant in the [studio-staging preview
build](https://github.com/supabase/supabase/pull/42963#issuecomment-3917178023)
below
- Visit the [Logs tab in the Braintrust Assistant
project](https://www.braintrust.dev/app/supabase.io/p/Assistant/logs)
and inspect the trace
<img width="4680" height="962" alt="CleanShot 2026-02-18 at 17 43 55@2x"
src="https://github.com/user-attachments/assets/c3a11b21-4e7f-4e90-bdab-a25ab8ee0d1f"
/>
<img width="2632" height="1288" alt="CleanShot 2026-02-18 at 17 45
04@2x"
src="https://github.com/user-attachments/assets/6c7b6ebc-5090-4ede-8f71-859ff7e386aa"
/>
**References**
- https://www.braintrust.dev/docs/integrations/sdk-integrations/vercel
- https://www.braintrust.dev/docs/instrument/custom-tracing
Closes AI-438
## Context
Related to this previous PR
[here](https://github.com/supabase/supabase/pull/42321)
Table Editor: Adding a CTA to the `HighQueryCost` UI to allow users to
proceed with fetching data despite the high query cost warning, to
prevent completely blocking the users from their workflows (realised
that certain heavy queries are required and this safeguard shouldn't be
creating dead-ends for users)
<img width="1159" height="264" alt="image"
src="https://github.com/user-attachments/assets/5fa01f7f-4442-4349-91f2-f4275e177f89"
/>
Clicking "Load more" will open a confirmation dialog, in which
proceeding to load the data will thereafter suppress this preflight
check for the table, for the rest of the browser session
<img width="450" height="305" alt="image"
src="https://github.com/user-attachments/assets/d3197a5d-a861-47a8-95da-e157972ce092"
/>
## Other changes
- Also bumped the query cost threshold from 100,000 to 200,000 - the
former might have been too aggressive 😓
- (Unrelated) Added query cost tooltip for cron jobs high query cost
warning
<img width="450" height="230" alt="image"
src="https://github.com/user-attachments/assets/d2c66972-7c4c-4f99-818c-e90a0991c2f5"
/>
This pull request introduces improvements to the handling of storage
endpoints in the Studio app, ensuring that storage operations utilize
the correct endpoint and enhancing maintainability through import path
updates and code clarity. The most significant changes are grouped
below:
**Storage Endpoint Handling:**
* The `useProjectEndpointQuery` hook now returns both `clientEndpoint`
and `storageEndpoint`, allowing storage operations to use a dedicated
endpoint when available.
* In the `StorageExplorerStateContextProvider`, the logic for
constructing the resumable upload URL now prefers `storageEndpoint` if
present, falling back to `clientEndpoint` otherwise. This ensures
uploads use the most appropriate endpoint.
* The context provider now sets `clientEndpoint` to `storageEndpoint`
when available, further aligning storage requests with the correct
endpoint.
* The dependency array for the provider effect now includes
`storageEndpoint`, ensuring state updates when the storage endpoint
changes.
**Code Quality and Maintainability:**
* Import paths in `storage-explorer.tsx` have been updated to use alias
(`@/`) references, improving clarity and maintainability. Type-only
imports are also used where appropriate, reducing bundle size and
potential circular dependencies.
**Code Clarity:**
* Added comments to chunk size calculations in the upload logic,
clarifying the rationale behind chunk sizing for different file sizes.
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Completion of batch edits on the table editor
## Demo
https://github.com/user-attachments/assets/ab5a7112-3dcc-456a-a5fc-1c9a99fccf34
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Queued add/edit/delete operations with optimistic UI, conflict
resolution, and queue-based flows
* Side-panel items showing queued add/delete row previews
* **UI**
* Pending-add placeholders plus a visible "DEFAULT" marker in grid cells
* Visual row states: green for pending adds, red with strike-through for
pending deletes
* Queue-based deletes can bypass confirmation when queue mode is enabled
* **Tests**
* Expanded tests covering queue conflict resolution and queue utilities
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <a@alaisteryoung.com>
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
For the new AI filters we should take a totally different approach.
Rather than using the URL as the source of truth, it should rather act
as a secondary state store. The first being local state in Snap that
gets loaded from the URL. By forcing this clear line we can always make
sure the URL is backed up with the right values and ensure state is
updated quickly.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Toggleable next‑gen filter bar with lifecycle that initializes and
syncs filters to the URL.
* Centralized filter API in table state for setting, clearing, and
sharing filters across components.
* **Improvements**
* Grid queries are project‑scoped, use placeholder previous data, and
reapply optimistic updates on refresh.
* Added MS SQL sorting warning and feature‑flag controls for
queue/operation behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Testing
- Make sure the old filters still work as expected
- Enable the new Headers, test out new filters approach (count is still
broken FYI, will fix that later)
## Context
Just adding some documentation to the more complex parts of the
dashboard in hopes to ease working on these parts for those who aren't
familiar
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Folder creation and updates in the SQL Editor now properly sync to the
backend with API calls, success notifications, and improved error
handling.
* Snippet save/upsert behavior updated: saves run via API with
optimistic handling and debounced execution; default automatic refresh
after save has been reduced to avoid unnecessary invalidations.
* **Documentation**
* Added a comprehensive SQL Editor guide covering UI, data flow, snippet
management, and improvement notes.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
TBD
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* OS-aware modifier-key label shown in UI (⌘ on macOS, Ctrl+ on others)
* Tooltips added to operation queue actions for improved usability
* **Bug Fixes**
* Warns before applying non-primary-key sorts on large tables
* Clarified access error messages for organizations and projects
* **Refactor**
* Redesigned hotkey handling and operation-queue shortcuts
* Operation queue view toggle and save flow refined (panel auto-closes
after save)
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Context
Related to this PR
[here](https://github.com/supabase/supabase/pull/42265)
If you were to update a cell twice, then save, the value that get's
saved is the first edited value.
There's a number of changes in this PR but the main thing is just
`useOperationQueueActions` to declare `operations` outside of
`handleSave` since `snap` wouldn't trigger the re-render of that
function in the dependency array.
## Other changes
- Refactored `useOperationQueueShortcuts.ts`
- Reuse an existing `useHotKey` method to handle the event listeners
- Remove unnecessary prop drilling, call the necessary hooks within it
instead
- Simplify its calling by only calling this hook within
`SaveQueueActionBar` (removed calling from `OperationQueueSidePanel`
- Add tooltip for OperatioItem "Remove operation"
- (Unrelated) Fix Table Editor sort "Apply sort" CTA not working for
large tables when applying sort on an indexed column (e.g primary key)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Operation queue view now toggles open and closed with a single action
* Simplified keyboard shortcuts: press **S** to save operations, **.**
to toggle the queue view
* **Bug Fixes**
* Sort operations on large tables with non-primary-key sorting now show
a confirmation warning and require explicit user approval before
applying
* **Improvements**
* Operation queue panel automatically closes after successfully saving
operations
* Enhanced UI with improved delete action feedback and refined visual
separators
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* Validate against empty name in FileExplorerRowEditing.tsx
* Update test
* Fix
* Opt to revert changes if saving empty string
* Nit
* Attempt to write tests with claude
* Trim whitespace in FileExplorerRowEditing when saving
* wip: explain tab in results editor
* updated to add sql explain
* updated to default back to results
* updated explain function
* updated case with multiple statements
* updated to reset explain query results
* added tests for semi colon comments
* feature: add explain w/ AI on pretty-explain tab (#41588)
* wip: added explain with AI
* wip: updated header with new buttons
* updated prompt
* remove any types
* removed unused flag
* updated header
* formatted code
* Use the .sql suffix when generating ids.
* Fix a bug where a new snippet would not show up in the snippet list until refresh.
* Add API routes which serve file snippets.
* Refactor the renameSnippet and moveSnippet to work with file snippets.
* Change the link to the SQL Editor.
* Minor fixes from CodeRabbit.
* Check the file/folder name for invalid chars.
* More fixes from CodeRabbit review.
* Fix minor issues.
* Use zod to parse the snippet ids when deleting.
* Try to fix snyk issue.
* Add validation to the GET content index route.
* Minor fixes.
* Show create a new folder, it was hidden by mistake.
* Add SNIPPETS_MANAGEMENT_FOLDER env var.
* Add snippets folder in the docker-compose.
* Add error toasts if the env var is not set.
* Add snippets management folder to the generateLocalEnv script.
* Revert the docker-compose changes, will be done in a followup PR.
* Revert also the snippets volume folder.
* Remove unneeded line.