## Context
Resolves FE-2794
Just addressing some friction points i ran into when setting up MFA for
my account under account preferences
## Changes involved
- Hitting enter at each step of setting up MFA will submit and proceed
(Previously didn't, had to click buttons)
- When logging in with MFA, automatically submit after entering 6 digits
- Refactored to use react hook form for `AddNewFactorModal` in
`FirstStep` and `SecondStep` + simplified the logic a little
## What kind of change does this PR introduce?
Feature / UX update.
## What is the current behavior?
Platform webhook deliveries cannot be retried from the deliveries table
or the delivery details sheet.
## What is the new behavior?
- Adds a retry action to individual platform webhook deliveries in the
endpoint deliveries table
- Adds a retry action to the shared delivery details sheet footer
- Limits retry to non-success deliveries
- Applies the table action hit area guidance from the design system
Successful deliveries should also not expose retry in this mock flow.
## Additional context
- Addresses DEPR-340.
- In the current mock implementation, queueing updates the existing
delivery in place: it sets the status to `pending`, clears
`responseCode`, and refreshes `attemptAt` to the current timestamp.
- The mock does not create a separate queued job or append a new
delivery record yet; the same delivery is resurfaced at the top of the
list because deliveries are sorted by latest attempt time.
Fixes#42357
Supersedes #42364
## Problem
When copying the URL of a file that is not in the currently opened
folder, the folder path is still included in that file URL.
## Solution
We actually always have the file path, use it directly instead of
rebuilding it from the storage explorer state
## How to test
1. Create a bucket and upload a file in it
2. Create a folder and upload a file in it
While the folder is selected, right click the root file uploaded in 1
and copy its URL. It should not contain the folder name. Same with the
dropdown menu that appears when hovering the file.
Ensure the observability link in the sidebar and command menu are
properly guarded by IS_PLATFORM to prevent them from showing in
self-hosted or CLI environments.
The logic is functionally the same (IS_PLATFORM && reportsEnabled), but
restructured with IS_PLATFORM as the outer check for clarity, and added
comments explaining the platform-only restriction.
https://claude.ai/code/session_01PG2TEGaSxaXZfXkbSBU3kQ
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES/NO
## What kind of change does this PR introduce?
Bug fix, feature, docs update, ...
## What is the current behavior?
Please link any relevant issues here.
## What is the new behavior?
Feel free to include screenshots if it includes visual changes.
## Additional context
Add any other context or screenshots.
Co-authored-by: Claude <noreply@anthropic.com>
This PR fixes some prettier issues:
- Bump and unify all prettier versions to 3.7.3 across teh whole repo
- Bump the SQL prettier plugin
- When running `test:prettier`, check `mdx` files also
- Run the new prettier format on all files
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## What kind of change does this PR introduce?
UI touch-up
## What is the current behavior?
Explorer rows in file storage is a bit rough around the edges.
## What is the new behavior?
- Consistent loaders
- Consistent icons
Also includes:
- Fix to `stroke-width` on files-bucket.svg as documented in icons.mdx
| Before | After |
| --- | --- |
| <img width="1024" height="563" alt="Buckets Storage AWS Healthy
Toolshed Supabase"
src="https://github.com/user-attachments/assets/055518b2-6d93-4c9d-879b-6e7dd51e0620"
/> | <img width="1024" height="563" alt="Buckets Storage AWS Healthy
Toolshed Supabase"
src="https://github.com/user-attachments/assets/fae05446-95d9-4ca1-b441-7cd39d1c6036"
/> |
## What kind of change does this PR introduce?
Chore
## What is the current behavior?
- We use the MCP client connect dialog in two places: Studio and Docs
- We duplicate image assets for each client in each of those two places
## What is the new behavior?
- Centralised assets
- Consolidation and simplification as a result of it all being a single
source-of-truth now
## To test
- [ ] Everything works as it did before across both Studio and
[Docs](https://supabase.com/docs/guides/getting-started/mcp)
- [ ] All MCP client images load as expected
## Problem
- The schema visualiser lacks editing capabilities which leads to a lot
of navigation (ediing tables, columns)
- ReactFlow prevents users from selecting table and column names (to
copy them). Diasbling drag and pan on those texts would make moving
items cumbersome
- Long table and column names are hidden and even hide other elements
## Solution
- Add menus for both tables and columns
- Truncate long names with ellipsis and add a tooltip
- Hide menus when exporting to png/svg
[Screen Recording 2026-03-12 at
10.10.08.webm](https://github.com/user-attachments/assets/b2780266-e874-41d1-ac82-7c2c4ba5abf2)
## feat(sso): improve SSO management UX (safe deletion + invitation type
selection)
This PR improves the SSO management experience by introducing a safer
deletion flow for SSO providers and allowing explicit control over
invitation authentication type.
## SSO Provider Deletion Improvements
The SSO provider deletion flow has been redesigned to better communicate
the impact of the action and prevent accidental destructive operations.
### UX Improvements
* Replace `ConfirmationModal` with `TextConfirmModal` in `SSOConfig`
* Require typing the SSO domain to confirm deletion
* Display the number of organization members authenticating via SSO who
will be removed
* Add destructive visual styling and clear warnings about irreversible
consequences
* Update confirmation button label to emphasize impact:
* `I understand, delete SSO provider and members`
### Warning Content
The modal now clearly communicates:
* The domain being deleted
* That SSO authentication will be disabled
* That SSO-authenticated members will be permanently removed
* That those members must be re-invited to regain access
If SSO members exist, a highlighted destructive warning box shows:
```
X organization member(s) who authenticate via SSO will be permanently removed
```
### Implementation Details
* Add `useOrganizationMembersQuery` to fetch organization members
* Calculate SSO members by filtering `is_sso_user === true`
* Only display the member warning when the count > 0
* Modal uses `variant="destructive"` and `size="small"`
This pattern follows the existing **Delete organization** confirmation
flow.
### Initial Delete Support
This PR also introduces the underlying deletion functionality:
* Add `useSSOConfigDeleteMutation`
* Add delete button (trash icon, danger styling) in the SSO config
footer
* Layout mirrors `CustomDomainDelete` pattern:
* delete button on the left
* save/cancel actions on the right
* Success toast shown after deletion
* Form resets to explicit default values after deletion
## Invitation Type Selection
Organizations with SSO configured can now explicitly choose the
authentication method when inviting new members.
Previously, invitations always inherited the inviter's authentication
method. This made it difficult to support mixed authentication
organizations.
### New Invitation Options
When SSO is enabled, the invite dialog now shows an **Invitation type**
dropdown:
* **Automatic (based on your account)**
Default behavior; inherits authentication method from the inviter.
* **Require SSO authentication**
Sends an SSO invitation.
* **Email/password authentication**
Sends a non-SSO invitation.
### Implementation Details
* Add `useOrgSSOConfigQuery` to detect if SSO is configured
* Add `requireSso` field to the form schema with enum:
* `auto`
* `sso`
* `non-sso`
* Only display the dropdown when the organization has an SSO provider
* Transform form values before sending to the backend:
```
sso -> { requireSso: true }
non-sso -> { requireSso: false }
auto -> {} (omit parameter)
```
* Update `OrganizationCreateInvitationVariables` to include optional
`requireSso`
* Preserve backward compatibility by only sending the field when
explicitly set
## Bug Fixes
* Attribute mapping preset buttons (Azure, GSuite, Okta) now properly
mark the form as dirty so the save button becomes enabled
* Form reset after deletion now uses explicit default values instead of
the last saved state
## Problems Solved
This PR addresses several UX issues:
1. Deleting an SSO provider previously used a simple confirmation with
no explanation of impact
2. Users could not see how many members would be affected by deletion
3. The destructive and irreversible nature of the action was not
visually emphasized
4. Invitations always inherited the inviter's auth method
5. Organizations could not intentionally mix SSO and non-SSO users
## Types
TypeScript types in `api-types` were updated to support the new
`require_sso` parameter.
---------
Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
(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>
## 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?
As we now have the internal error code mapping in `shared-data`, thought
it better to move away from the GraphQL endpoint and leave that for
external use. The error code popovers in studio now rely on shared-data,
meaning instant loads and no rate limiting.
When the dashboard hits a DB connection timeout, users currently see a
raw error message with no
path forward. This PR adds an inline troubleshooting system that detects
known error types and
surfaces contextual next steps — restart the DB, read the docs, or debug
with AI.
## Changes
- New ErrorDisplay component (packages/ui-patterns) — styled error card
with a title, monospace error
block, optional troubleshooting slot, and a "Contact support" link that
always renders. Accepts
typed supportFormParams to pre-fill the support form.
- Error classification in handleError (data/fetchers.ts) — on every API
error, the message is tested
against ERROR_PATTERNS. If matched, handleError throws a typed subclass
(ConnectionTimeoutError
extends ResponseError) instead of a plain ResponseError. Stack traces
now show the exact error
class. All existing instanceof ResponseError checks continue to work.
- ErrorMatcher component — reads errorType from the thrown class
instance, does an O(1) lookup into
ERROR_MAPPINGS, and renders the matching troubleshooting accordion as
children of ErrorDisplay.
Falls back to plain ErrorDisplay for unclassified errors.
- Connection timeout mapping — first error type wired up, with three
troubleshooting steps: restart
the database, link to the docs, and "Debug with AI" (opens the AI
assistant sidebar with a
pre-filled prompt).
- Telemetry — three new typed events track when the troubleshooter is
shown, when accordion steps are
toggled, and which CTAs are clicked.
## Adding a new error type
1. Add a class to types/api-errors.ts
2. Add { pattern, ErrorClass } to data/error-patterns.ts
3. Create a troubleshooting component in errorMappings/
4. Add an entry to error-mappings.tsx
## Context
Related to FE-2557
Part of shifting manually written dashboard queries into
packages/pg-meta where
- pg-meta can be code owners of
- we can write tests for the queries
This PR just shifts all the `.sql.ts` files that we previously created
into packages/pg-meta
There's still other areas where we need to shift over as well which I'll
address in subsequent PRs
## Notable changes
- `getTableRowsCountSql` -> Opted to shift `formatFilterValue` logic out
before calling this method (ref `table-rows-count-query`)
- `getDeleteOldCronJobRunDetailsByCtidSql` -> Opted to shift
`validatePageNumber` logic out before calling this method (ref
`CronJobsTab.useCleanupActions`)
## What kind of change does this PR introduce?
Refactor, cleanup, and docs update.
## What is the current behavior?
After the page-title rollout, `ProjectLayout` is still in a transitional
state:
- it accepts a deprecated `title` prop
- it still supports a separate `browserTitle.surface`
- wrapper layouts are split between passing `title` directly and passing
`browserTitle.section`
That makes the API harder to reason about than it needs to be, even
though the rendered titles are already correct.
## What is the new behavior?
This cleanup finishes the API simplification that came out of the
stacked PR review:
- wrapper layouts stay `title`-first for DX
- `ProjectLayout` no longer accepts `title`
- `product` is now the single source of truth for the project-surface
title segment
- `browserTitle` is now only used for extra browser-title metadata
(`entity`, `section`, `override`)
- the remaining project-scoped callers now pass `browserTitle.section`
when they need a section label
- docs now reflect the final pattern instead of the transitional one
Rendered page titles stay the same.
## Additional context
Checks run:
- `pnpm --filter studio exec vitest --run lib/page-title.test.ts
components/layouts/ProjectLayout/index.test.tsx`
- `pnpm --filter studio typecheck`
- `pnpm exec prettier --check ...` on touched files
This is intended as the post-rollout cleanup PR based on Joshen's review
feedback across the stacked title changes.
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Context
Small one - while on the database replication page, if you open the
Connect Dialog and change the "type" field, the destination panel opens
up. Happening cause the string for `useQueryState` conflicts here - both
are using `type`
Fix is just to update the string for `useQueryState` for the
DestinationPanel component, changed it to `destinationType`
## 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?
This introduces Query Insights. It's the first edition of possible
future updates. This takes our old prototype and builds upon it for a
more action driven insights view.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
### Summary
This PR adds a dismissable modal that prompts paid org users to fill in
their billing address. We need billing addresses for tax compliance and
the existing banner hasn't been as effective (~10k orgs still missing).
The modal shows on page load when all of these are true:
- ConfigCat flag `enableBillingAddressModal` is on
- Org is on a paid plan (not free)
- Org does not have billing address set
- Org is not partner-managed
- User has BILLING_WRITE permission on stripe.customer
The modal can be dismissed via the close button, but re-opens on every
page navigation.
Once the user saves a valid address, the organizations query is
invalidated and organization_missing_address flips to false - the modal
stops appearing permanently.
<img width="1256" height="703" alt="Screenshot 2026-03-05 at 4 22 11 PM"
src="https://github.com/user-attachments/assets/57e7d1b8-b3b6-4366-ad23-60910a0defe8"
/>
### Testing
#### Automated Tests
I've added unit tests in this PR
#### Manual testing
Manual test cases:
- Free org - modal does not appear
- Partner-managed org - modal does not appear
- User with "developer role" modal does not appear
- Configcat Flag disabled - modal does not appear
- Dismiss modal, navigate to another page - modal re-opens
- Fill form and save - modal closes and does not reappear
- API failure loading billing data - shows error state with Retry button
---------
Co-authored-by: Ignacio Dobronich <ignacio@dobronich.com>
## Summary
When the `connectSection` PostHog flag is unresolved (`undefined`) —
e.g. during loading or if PostHog is unreachable — the header Connect
button renders nothing (`null`), making it a no-op. This changes the
fallback to render the legacy `<Connect />` dialog instead, so the
button always works.
## Changes
- Remove `isFlagResolved` gate in `LayoutHeader` — render `<Connect />`
(legacy) whenever `connectSection !== 'connect'`, including when
`undefined`
## Testing
Tested on Vercel preview:
- [x] Flag returns `'connect'` — ConnectSheet opens
- [x] Flag returns `'getting-started'` or `false` — legacy Connect
dialog opens
- [x] Flag is `undefined` (unresolved) — legacy Connect dialog opens
instead of nothing
## 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>
Stacked PR 4/5 for page title improvements. Includes account and
organization-level title updates plus organization list/selector page
titles.
_Base:
[dnywh/feat/page-titles](https://github.com/supabase/supabase/pull/43538)_
---
## What kind of change does this PR introduce?
- Resolves FE-1960
- Resolves FE-1983
- Resolves DEPR-207
## What is the current behavior?
Page titles between surfaces are inconsistent and vague. Sometimes they
say the product name:
```
My Project | My Org | Supabase
```
...even when on a specific surface like Database > Tables.
Other times they show the entity name but skip over the project or org
name :
```
Edge Functions | Supabase
```
## What is the new behavior?
Account and organization-level title updates plus organization
list/selector page titles, adopting the layout title format introduced
in https://github.com/supabase/supabase/pull/43538:
```
users | Table Editor | My Project | My Org | Supabase
hello-world | Logs | Edge Functions | My Project | My Org | Supabase
Backups | Database | My Project | My Org | Supabase
Authentication | My Project | My Org | Supabase
```
That format is:
entity, section, surface, project, org, brand
## Additional context
Related stacked PRs also based on the the original
[dnywh/feat/page-titles](https://github.com/supabase/supabase/pull/43538)
branch:
- https://github.com/supabase/supabase/pull/43534
- https://github.com/supabase/supabase/pull/43535
- https://github.com/supabase/supabase/pull/43537
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## What kind of change does this PR introduce?
Feature
## What is the current behavior?
- Platform webhooks have a ‘tap target on tap target’ pattern with
`DropdownMenu` being on top of a clickable `TableRow`
- Misclicks are common (at least for me)
- @jordienr recently added the `hit-area` Tailwind plugin that helps
with misclicks
- https://github.com/supabase/supabase/pull/43636
## What is the new behavior?
- The aforementioned `DropdownMenu` in platform webhooks now uses
`hit-area` to avoid misclicks
- Design system documentation
- Extracted `hit-area` Tailwind plugin to shared packages so it can be
used in design-system as well as studio
## Preview
https://github.com/user-attachments/assets/89f9110a-6c99-4eed-a386-a6f646b1f4f6
Feature
## What is the current behavior?
Incident banner logic depends on StatusPage and Supabase project for
metadata.
## What is the new behavior?
New incident banner logic that depends only on incident.io. Displays in
non-production environments for now because I haven't wired up the rest
of the workflow. This is just to allow a total end-to-end
testing/playground for test incidents <-> Slack <-> preview dashboard
for people to try out the UX.
## Additional context
You can test using my [test
incident](https://app.incident.io/supabase/incidents/405). This has
severity minor, so the preview site should have a banner. Toggle to
informative, hard refresh dashboard with cache off, and banner should
disappear. Toggle back to minor, hard refresh without cache again, and
banner should reappear. Same thing if you edit the "Banner shown" field
from 1 to -1 and back.
## 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?
- Bring back the old home page for self hosted, because the new one does
not work for self hosted users
- Unit tests to catch this in the future
Fix `graphql_public` schema not showing in legacy exposed schemas
selector
## Summary
- The `graphql_public` schema was getting filtered out of the exposed
schemas multi-select when the API grant toggles feature flag is disabled
- `ExposedSchemaSelector` (new mode) already had an exception for
`graphql_public` – this just adds the same exception to the legacy
mode's schema filter
## Test plan
- [ ] Disable the `tableEditorApiAccessToggle` feature flag
- [ ] Go to Settings > API > exposed schemas
- [ ] Confirm `graphql_public` appears in the schema list and is
selectable
## 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?
Formalising our status code component that was introduced in the new
charts + update auth overview page.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a StatusCode UI component to display HTTP methods and status
codes with color-coded indicators.
* Added a demo showcasing multiple StatusCode examples and alignment
variants.
* **Documentation**
* Added a documentation fragment and sidebar entry for Status Codes with
a preview of the demo.
* **Refactor**
* Updated an Auth Overview view to use the new StatusCode component for
consistent status rendering.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Adds a new toggle in:
<img width="1161" height="356" alt="Screenshot 2026-03-10 at 17 17 06"
src="https://github.com/user-attachments/assets/b09ac1aa-a8f5-4fb4-8771-f113b140eac8"
/>
Other changes:
- form submissions with no table/function changes were failing because
an empty string got passed to executeSql. Added an early return when
there's nothing to execute
To test:
- Ensure the form is still in working order
- Create some tables and functions with the toggle on add off and make
sure your selected default applies
## What kind of change does this PR introduce?
Feature that resolves DEPR-321.
## What is the current behavior?
From @dshukertjr:
> Users of free and pro orgs frequently struggle to figure out how to
add teammates to a project.
## What is the new behavior?
Project Settings → General now has a Project access section showing who
can access the project (email + role), with a link to team management
(_Manage members_ or _View team_ for limited users). Large member lists
are truncated with +N more.
| Permutations |
| --- |
| <img width="1462" height="544" alt="CleanShot 2026-03-06 at 17 00
00@2x"
src="https://github.com/user-attachments/assets/68e5519f-3851-4ab8-a364-9fcb222fbcb7"
/> |
| <img width="1486" height="676" alt="CleanShot 2026-03-06 at 16 59
48@2x"
src="https://github.com/user-attachments/assets/e1b85bb5-6fbd-46ec-9b13-15501defd030"
/> |
| <img width="1464" height="566" alt="CleanShot 2026-03-06 at 16 59
34@2x"
src="https://github.com/user-attachments/assets/e9fdc188-cf79-4af9-8b3c-313e98256109"
/> |
| <img width="1438" height="654" alt="CleanShot 2026-03-06 at 17 11
25@2x-83D06149-E4AE-4AC0-98D9-FBBE10A58C8C"
src="https://github.com/user-attachments/assets/8a6e1aa2-76bb-486e-999a-1df4f88c3692"
/> |
## Additional context
Behaviour is based on user role visibility, not a special plan-only
toggle. Team+ orgs are more likely to hit limited/project-scoped cases;
free/pro are usually org-wide access.
## What kind of change does this PR introduce?
Copywriting improvements
## What is the current behavior?
The “missing tax ID” banner:
- Is longer than it needs to be
- Therefore overflows on smaller viewports
- Has unnecessarily qualifications despite having a dismiss button
- Has funky capitalization
## What is the new behavior?
- Tighter copywriting with less redundancy
| Before | After |
| --- | --- |
| <img width="1024" height="563" alt="AWS Healthy Toolshed
Supabase-8B1E57CE-72A6-4C7F-918F-71C1842CBDD3"
src="https://github.com/user-attachments/assets/755fd9ac-50e7-4540-9dd3-529e37bdeaff"
/> | <img width="1024" height="563" alt="AWS Healthy Toolshed
Supabase-A2B65D23-103A-4146-BE6A-DEAC592646D0"
src="https://github.com/user-attachments/assets/deefb639-0670-4d92-8b75-bc0080bfb587"
/> |
## What kind of change does this PR introduce?
UI nit changes
## What is the current behavior?
- We use big dots `•` to separate semantically different sets of text
that are in the same row
- This looks a bit odd given how large the dot is to text
- We put _Project Settings_ in its own sidebar section but without a
separator like all other sidebar sections
## What is the new behavior?
- Use the smaller dots `·` to separate text
- Place a separator above _Project Settings_ in sidebar
| Before | After |
| --- | --- |
| <img width="1342" height="711" alt="AWS Healthy Toolshed
Supabase-70BD1825-8077-4D1B-84C1-831A4ADAFC0B"
src="https://github.com/user-attachments/assets/70246009-a3c7-4b5c-8d75-122140a637d1"
/> | <img width="1342" height="711" alt="AWS Healthy Toolshed Supabase"
src="https://github.com/user-attachments/assets/e3fc13e4-923d-472e-aaf9-d689e890697b"
/> |
## Context
Related to dashboard scalability
Previous PR: https://github.com/supabase/supabase/pull/42856
Note: Changes are all feature flagged still and I'm still not entirely
convinced with the current UX
Will iterate as as go along, and only make this publicly available when
we're satisfied with the behaviour
Adds a "Dashboard preference" section to the project settings
<img width="265" height="740" alt="image"
src="https://github.com/user-attachments/assets/6ce1aa19-26c2-47c6-a9c4-595137266631"
/>
In which users can then select which database they'd like to use for
read queries run from the dashboard
Note: Everything is local storage for now, but we'd need middleware
support if we want to make this setting persist for all users on the
project
<img width="791" height="434" alt="image"
src="https://github.com/user-attachments/assets/e651d6d9-fed4-4da4-b552-c9f93f8d46d3"
/>
Added a dialog as well to further explain what this implies
<img width="610" height="312" alt="image"
src="https://github.com/user-attachments/assets/0aa957af-cb51-476f-aa79-8948a7cbe5ae"
/>
## To test
- Choosing a replica in dashboard preferences will only affect the table
editor as thats the only place that's set up so far to use a replica for
read queries (I'll need to follow up for other parts of the dashboard in
subsequent PRs)
Stacked PR 3/5 for page title improvements. Includes Logs and
Observability layout title adoption, unified logs title cleanup, and
small route title fixes.
_Base:
[dnywh/feat/page-titles](https://github.com/supabase/supabase/pull/43538)_
---
## What kind of change does this PR introduce?
- Resolves FE-1960
- Resolves FE-1983
- Resolves DEPR-207
## What is the current behavior?
Page titles between surfaces are inconsistent and vague. Sometimes they
say the product name:
```
My Project | My Org | Supabase
```
...even when on a specific surface like Database > Tables.
Other times they show the entity name but skip over the project or org
name :
```
Edge Functions | Supabase
```
## What is the new behavior?
Logs and Observability adopts the layout title format introduced in
https://github.com/supabase/supabase/pull/43538:
```
users | Table Editor | My Project | My Org | Supabase
hello-world | Logs | Edge Functions | My Project | My Org | Supabase
Backups | Database | My Project | My Org | Supabase
Authentication | My Project | My Org | Supabase
```
That format is:
entity, section, surface, project, org, brand.
Also includes unified logs title cleanup, and small route title fixes.
## Additional context
Related stacked PRs also based on the the original
[dnywh/feat/page-titles](https://github.com/supabase/supabase/pull/43538)
branch:
- https://github.com/supabase/supabase/pull/43534
- https://github.com/supabase/supabase/pull/43536
- https://github.com/supabase/supabase/pull/43537
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>