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
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`)
## 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>
## 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
## 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.
## 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 -->
## 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)
### Changes
- Adds a dismissible banner prompting paid org users to add a Tax ID to
their billing settings
- Only shown to users with billing read permissions on orgs with a paid
plan and no Tax ID set
- Dismissal is persisted per-org via localStorage; banner also
auto-hides when a Tax ID is added
### Testing
- Log in as a user with no billing permissions into a Free Plan Org with
no tax id: no banner is shown
- Log in as a user with billing permissions into a Free Plan Org with no
tax id: no banner is shown
- Log in as a user with billing permissions into a Paid Plan Org with no
tax id
- Assert banner appears at the top
- Head to `/org/_/billing` with a paid Org. Change your billing country
to a not support one (like Paraguay) and click save. Assert that the
banner disappears. Change it back to continue testing.
- Click dismiss: banner disappears and stays dismissed across
navigation/refresh
- Log in as a user with billing permissions into a different Paid Plan
Org with no tax id
- Add a Tax ID via billing settings, assert that the banner disappears
immediately
<img width="1911" height="50" alt="image"
src="https://github.com/user-attachments/assets/d6208d6d-0939-4ff6-9613-5c687e7c622e"
/>
## 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?
- Added tracker when the main ai button was pressed
- Added new event to track "Open in" third party apps
- Added 2 missing telemetry sources
## Problem
While working on the phased PostHog Attribution rollout (GROWTH-625 /
GROWTH-668) — specifically the initial referrer handoff across the app
boundary — we discovered that `parseFirstReferrerCookie` was returning
`null` even when the cookie was visibly present in the browser.
The root cause: `serializeFirstReferrerCookie` calls
`encodeURIComponent(JSON.stringify(data))`, but Next.js `cookies.set()`
encodes the value again, producing a double-encoded cookie. On the read
side, `parseFirstReferrerCookie` only decodes once, so `JSON.parse`
receives a still-encoded string and fails. The `try/catch` swallows the
error and returns `null`.
Confirmed in production: the raw cookie value starts with `%257B%2522`
(double-encoded `%` characters). A single `decodeURIComponent` produces
`%7B%22referrer%22...` — still URL-encoded, not valid JSON. This was
blocking the cross-app attribution handoff that GROWTH-625 depends on.
## Changes
- **Serializer**: Removed `encodeURIComponent` from
`serializeFirstReferrerCookie` — Next.js `cookies.set()` already handles
encoding
- **Parser**: Made `parseFirstReferrerCookie` resilient to both
encodings — tries single decode first, falls back to double decode for
existing cookies in the wild (365-day TTL means legacy cookies persist
up to a year)
- **Test**: Added unit test for the double-encoded legacy cookie format
## Testing
- 35/35 common unit tests pass, 12/12 www middleware tests pass
- Verified locally: Google → www (localhost:3000) → Studio
(localhost:8082). Console logs confirmed `parseFirstReferrerCookie`
returned the full data object instead of null
- Confirmed in production that existing cookies are double-encoded and
the fix correctly handles them
Ref: GROWTH-625 / GROWTH-668
Update reference rendering files to support additional values in tsdoc.
---------
Co-authored-by: Jonathan Summers-Muir <MildTomato@users.noreply.github.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?
Right now the new filter bar just does not work on mobile. It fully
collapses and does not appear correctly. This make it stack on smaller
screens and shows it to be visible. Works on smaller tabs
Note: there is a bit of awkwardness on certain screen sizes where its
one long row, will fix that later. This is better than nothing right now
## Problem
The Phase 1 mw_diag monitoring dashboard wasn't showing any data despite
the middleware PR (#43413) being live in production.
Next.js `response.cookies.set()` URL-encodes cookie values, so
`hit=1&would_stamp=0&has_cookie=0` becomes
`hit%3D1%26would_stamp%3D0%26has_cookie%3D0` in `document.cookie`. Our
`parseMwDiagCookie` was passing that encoded string directly to
`URLSearchParams`, which splits on literal `&` and `=` — the encoded
`%26`/`%3D` delimiters were invisible to it. Result: `params.get('hit')`
always returned `null`, so every diagnostic cookie was silently dropped.
## Changes
- Add `decodeURIComponent()` before `URLSearchParams` in
`parseMwDiagCookie`
- Add 3 test cases covering URL-encoded cookie values (matching what
Next.js actually produces in production)
## Testing
- All 34 unit tests pass (31 existing + 3 new)
- Verified locally with Playwright: manually set the URL-encoded cookie
format on localhost:8082, confirmed `parseMwDiagCookie` now returns
`{hit: true, ...}` and the data flows through to `PageTelemetry`
GROWTH-625
## 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?
Feature — A/B experiment for a new pricing calculator on the `/pricing`
page, gated behind a PostHog feature flag.
## What is the current behavior?
The pricing page shows a single compute pricing section
(`PricingComputeSection`) to all visitors with no experimentation
support.
## What is the new behavior?
- Introduces a **pricing calculator A/B experiment**
(`pricingCalculatorExperiment`) using PostHog feature flags evaluated
client-side.
- **Control variant**: Renders the existing `PricingComputeSection` (no
change).
- **Test variant**: Renders a new `NewPricingComputeSection` with:
- A plan selector toggle (Pro / Team)
- An interactive compute calculator with slider-based instance sizing
- Ability to add/remove multiple project instances
- Live monthly cost estimate breakdown (plan + compute - credits)
- Expandable compute pricing table with detailed specs
- Adds `getFeatureFlag` and `onFeatureFlags` methods to the shared
`PostHogClient` for client-side flag evaluation on www pages (where
server-side evaluation lacks full person context).
## Additional context
- The experiment is scoped to the `/pricing` page only.
- New components (`NewPricingComputeSection`,
`NewComputePricingCalculator`) are created alongside the existing ones —
the control path is completely untouched.
- Feature flag evaluation happens client-side because www pages don't
have full person context on the server.
- Telemetry type `PricingCalculatorExperimentExposedEvent` is added to
`telemetry-constants.ts`.
---------
Co-authored-by: Sean Oliver <882952+seanoliver@users.noreply.github.com>
Co-authored-by: Mert YEREKAPAN <mertyerekapan@gmail.com>
Co-authored-by: Mert YEREKAPAN <33198490+myerekapan@users.noreply.github.com>
## Summary
The `homeNew` PostHog experiment has concluded. This PR graduates it by
making the new homepage (`ProjectHome`, formerly `HomeV2`) the permanent
default for all users, and removes all dead code from the old
experiment.
## Changes
- Remove `homeNew` PostHog feature flag checks and `home_new` experiment
exposure tracking from 3 files
- Rename `HomeNew/` → `ProjectHome/` directory and `HomeV2` →
`ProjectHome` export
- Delete old `Home/Home.tsx` component (shared components like
`ProjectList/` are kept — still used by org pages)
- Delete `pages/project/[ref]/building.tsx` and add a server-side
redirect from `/project/:ref/building` → `/project/:ref` to prevent 404s
during rollout (old cached JS bundles may still route to `/building`)
- Simplify `ContentWrapper` building-state logic in `ProjectLayout` —
always redirect building projects to home, always suppress building
interstitial on home page
- Always route to `/project/{ref}` after project creation (remove
`/building` path)
- Update all Observability imports from `HomeNew` → `ProjectHome`
## Self-hosted behavior change
Self-hosted Studio previously showed the old `Home` component (client
libraries + example projects) since PostHog flags don't load. This PR
changes self-hosted to show `ProjectHome` (TopSection with service
status + instance diagram, advisor, custom reports). All sections query
backend APIs that exist on self-hosted. E2E tests pass against the
self-hosted build.
## Testing
- [x] `pnpm turbo run build --filter=studio` passes
- [x] No remaining references to `homeNew`, `home_new`, or `HomeNew` in
codebase
- [x] No broken imports to deleted files
- [x] Self-hosted E2E tests pass (145 passed, 1 flaky, 4 skipped)
- [x] `/building` redirect added to both platform and self-hosted config
blocks
**Quick test:**
1. Navigate to any project homepage — should render the ProjectHome
component
2. Create a new project — should redirect to `/project/{ref}` (not
`/building`)
3. Visit a project in `COMING_UP` state on a non-home route — should
redirect to home
4. Visit `/project/{ref}/building` directly — should 302 redirect to
`/project/{ref}`
## Linear
- fixes GROWTH-671
## Context
We reached to a consensus that we'll keep manually written queries
within the `pg-meta` package
I'll shift queries over in several PRs but wanted to double check if the
changes here is a good folder structure
## Changes involved
- Am organizing dashboard queries in `pg-meta` based on product
- So folder structure will be `/sql/studio/[product]/*.ts`
- Every constant will be exported directly from `pg-meta`'s index
- So consumption in dashboard will just be `import { xxx } from
'@supabase/pg-meta`
cc @avallete and @soedirgo on this one - lemme know if this is alright,
or if there's a preferred way to do this
PostHog flagged our SDK as outdated — we were on 1.257.2, latest is
1.357.0.
**Changes**
- Bumped `posthog-js` in `packages/common/package.json` from `^1.257.2`
to `^1.333.0` (resolved to 1.357.0)
- Updated lockfile
**Why is the lockfile diff so large?**
posthog-js added several new dependencies between 1.257.2 and 1.357.0: a
full `@opentelemetry/*` stack (for opt-in log exporting),
`@posthog/core` and `@posthog/types` (internal monorepo split),
`dompurify`, and `query-selector-shadow-dom`. None of these affect our
bundle unless explicitly enabled — they're opt-in features. The lockfile
entries are large because pnpm records each package with its full
resolution tree and checksums.
**Testing**
Spun up the full local stack and verified all three PostHog endpoints
return 200 with the new SDK version:
- `/e/` (event capture) — pageviews firing correctly
- `/flags/` (feature flag evaluation) — flags loading correctly
- `/i/v0/e/` (identify) — user identification working
No breaking changes in any of the 16 releases between our old and new
version (all Minor/Patch Changes). TypeScript compilation clean across
all apps.
GROWTH-589
## Problem
The `_sb_first_referrer` cookie isn't working. The www middleware
matcher explicitly excludes `/dashboard` and `/docs`, so the cookie
never gets stamped for Studio or Docs traffic. PostHog confirmed: only 1
event with `first_referrer_cookie_present=true` out of ~46.5M Studio
pageviews in the last 7 days.
## Background: what the matcher does
In Next.js, the `matcher` config controls which incoming requests the
middleware function even runs on. If a path doesn't match, the
middleware is skipped entirely — the request passes through untouched.
If it matches, the middleware runs and can mutate the response (set
cookies, headers, etc.).
This matters because Studio's SPA navigation works via silent
`/_next/data/` JSON fetches. If middleware runs on those requests and
returns `NextResponse.next()` with any mutations, it breaks those
fetches and causes full page reloads instead of client-side transitions.
## What we tried before
| PR | www runs on `/dashboard`? | Studio `proxy.ts` runs on all routes?
| Result |
|---|---|---|---|
| **#42768** (Attempt 1) | ✅ Yes — and also intercepts `_next/data` | ✅
Yes — `matcher` config removed, stamps cookie everywhere | Full page
reloads in Studio |
| **#43129** (Full revert) | ❌ No — www middleware deleted entirely | ❌
No — restored to `matcher: '/api/*'` only | Back to baseline, no cookie
stamping anywhere |
| **#43153** (Attempt 2) | ❌ No — `/dashboard` explicitly excluded | ✅
Yes — `matcher` config removed again, stamps cookie everywhere | Full
page reloads in Studio again |
| **#43189** (Attempt 3) | ❌ No — same as #43153 | ✅ Yes — `matcher`
config still removed, cookie stamping made conditional | Still broken |
| **#43190** (Ivan's fix) | ❌ No — `/dashboard` still excluded | ❌ No —
restored to `matcher: '/api/*'` only | Works — but cookie never stamps
for `/dashboard` traffic |
| **#43413** (this PR) | ✅ Yes — sets diagnostic cookie only, no
attribution stamping yet | ❌ No — unchanged, still `matcher: '/api/*'`
only | ❓ Untested in prod |
The common factor in every failure: Studio's `proxy.ts` ran on all
routes (including `_next/data` requests), which broke SPA navigation.
This PR is the first one that runs www middleware on `/dashboard` while
Studio's `proxy.ts` stays in its original narrow `/api/*` scope.
## What changed
This is Phase 1 of a two-phase rollout. We remove `dashboard|docs` from
the matcher's negative lookahead so www middleware runs on those paths —
but instead of stamping cookies, we set a short-lived (60s) diagnostic
cookie `_sb_mw_diag` on `/dashboard` and `/docs` requests.
The diagnostic cookie encodes
`hit=1&would_stamp={0|1}&has_cookie={0|1}`, which Studio telemetry reads
on the initial pageview and reports to PostHog as `mw_diag_hit`,
`mw_diag_would_stamp`, and `mw_diag_has_existing_cookie` properties.
A cookie rather than a header because response headers aren't readable
by JS. It also tests the actual Set-Cookie mutation path that Phase 2
will use (which is what Next.js issue #41885 is specifically about).
Phase 1 answers two key questions before we commit to Phase 2:
1. Does expanding the matcher break Studio SPA navigation?
2. What % of /dashboard arrivals would get a first-referrer cookie
stamped in Phase 2?
## Phase 2 readiness criteria
**Important caveat**: `mw_diag_*` data reflects consented users only and
may under-represent first-visit anonymous traffic. The Phase 2 decision
should account for this — the actual middleware execution rate is likely
higher than what PostHog reports.
### PostHog query spec
**Middleware execution rate**: Of all Studio initial pageviews on
`/dashboard` or `/docs` paths, what percentage have `mw_diag_hit =
true`? Expected: >= 90%. Below 70% warrants investigation (could
indicate edge caching bypassing middleware, or a matcher configuration
issue).
```
Filter: event = "$pageview" AND (current_url contains "/dashboard" OR current_url contains "/docs")
Breakdown: mw_diag_hit (true vs null/missing)
Metric: count(mw_diag_hit = true) / count(all) * 100
```
**Would-stamp rate**: Of events with `mw_diag_hit = true`, what
percentage have `mw_diag_would_stamp = true`? This tells us what
percentage of Phase 2 traffic would actually get a cookie stamped. No
hard threshold — unexpected values (< 5% or > 95%) suggest a logic bug
worth investigating before Phase 2.
```
Filter: event = "$pageview" AND mw_diag_hit = true
Breakdown: mw_diag_would_stamp (true vs false)
Metric: count(mw_diag_would_stamp = true) / count(all) * 100
```
**Existing cookie rate**: Of events with `mw_diag_hit = true`, what
percentage have `mw_diag_has_existing_cookie = true`? This tells us how
many users already have the cookie from a prior www visit.
```
Filter: event = "$pageview" AND mw_diag_hit = true
Breakdown: mw_diag_has_existing_cookie (true vs false)
Metric: count(mw_diag_has_existing_cookie = true) / count(all) * 100
```
### Go / no-go threshold table
| Signal | Go | Investigate | No-Go |
|---|---|---|---|
| `mw_diag_hit` rate (% of /dashboard+/docs pageviews) | >= 90% | 70-90%
| < 70% |
| SPA navigation errors (Sentry / Vercel logs) | No increase | < 0.1%
increase | > 0.5% increase |
| Middleware p99 latency (Vercel function logs) | < 50ms added |
50-100ms | > 100ms |
| Sample volume in first 24h | > 1,000 events | 100-1,000 (extend
window) | < 100 (insufficient data) |
## Changes
- `apps/www/middleware.ts`: Removed `dashboard|docs` from matcher; added
`isDashboardOrDocs` guard that sets `_sb_mw_diag` diagnostic cookie
instead of stamping attribution
- `apps/www/middleware.test.ts`: 12 tests covering cookie stamping on
www paths, diagnostic cookie encoding for all scenarios (external
referrer, direct nav, internal referrer, existing cookie)
- `packages/common/first-referrer-cookie.ts`: Exported
`MW_DIAG_COOKIE_NAME`, `MwDiagData` type, and `parseMwDiagCookie()`
helper
- `packages/common/telemetry.tsx`: Reads `_sb_mw_diag` on initial Studio
pageview; reports `mw_diag_*` properties to PostHog
## Testing
Unit tests pass (13/13 www, 31/31 first-referrer-cookie). Production
validation needed:
- [ ] Studio SPA navigation works (tab changes, SQL editor, no full page
reloads)
- [ ] PostHog shows `mw_diag_hit = true` on Studio initial pageviews
- [ ] `mw_diag_would_stamp` distribution looks reasonable before
enabling Phase 2
- [ ] Monitor 24h before Phase 2
Ref: GROWTH-625 / GROWTH-668
## 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 is something we've discussed for a while. A shared place for error
codes and their mappings, descriptors etc. Available for all projects in
the monorepo.
## What kind of change does this PR introduce?
Bug fix: custom icons now respect their source SVG’s stroke/fill and
stroke-width instead of always getting a global stroke.
## What is the current behavior?
Every custom icon gets `stroke="currentColor"` and `strokeWidth={2}`
from `createSupabaseIcon`, so fill-only logos get an extra stroke and
icons designed at `stroke-width="1"` (e.g. postgres, auth) render too
thick. Call sites and the design-system grid needed workarounds
(`strokeWidth={0}`, `FILL_ONLY_ICONS`, `STROKE_WIDTH_FROM_SOURCE`).
## What is the new behavior?
The icon build reads root SVG attributes (`fill`, `stroke`,
`stroke-width`, etc.) and passes them as per-icon defaults. Fill-only
icons (chatgpt, claude, axiom, last9) have `stroke="none"` in source and
render with no stroke; stroke icons keep their source stroke-width (e.g.
postgres at 1). No `strokeWidth={0}` or allowlists needed at call sites
or in the icon grid.
| Before | After |
| --- | --- |
| <img width="1826" height="552" alt="CleanShot 2026-03-05 at 10 53
31@2x-3D63CEF0-1132-44F5-A382-730346432F1E"
src="https://github.com/user-attachments/assets/9caf73fa-351b-4ea2-a420-b3339f934742"
/> | <img width="1814" height="552" alt="CleanShot 2026-03-05 at 10 53
40@2x-514FC8BD-D30F-4D23-B209-0ECD6D13A184"
src="https://github.com/user-attachments/assets/936ea5a5-dae0-413f-8545-b90a502cea69"
/> |
## Additional context
- Added `stroke="none"` to the four fill-only source SVGs;
sentry/grafana/otlp/datadog already had `stroke-width="0"`.
- `createSupabaseIcon` only applies `color`/`strokeWidth` when the
consumer passes them, so `svgDefaults` from the build are used
otherwise.
- Removed workarounds from `icons.tsx` and GuidesSidebar; updated
icons.mdx (defaults + fill-only guidance).
Allows users to select logs and copy their contents for debugging, or
pass them on to assistant with one click.
## To test
- go to logs or log explorer
- select some logs
- try copying as json, markdown, or sending it to assistant.
## What kind of change does this PR introduce?
- UI fixes and cleanup
## What is the current behavior?
- We use the _Anthropic_ logo for _Claude Code_ in the MCP connector
panel
- We have a bunch of redundant dark mode logos (visually the same as
their light mode siblings)
| Before | After |
| --- | --- |
| <img width="987" height="373" alt="Krosno Toolshed
Supabase-03CD5E6F-53E6-4282-9087-ACB9F67B6DDA"
src="https://github.com/user-attachments/assets/ca7b5d9c-2a2b-4520-8bd4-8cf26c759c73"
/> | <img width="987" height="373" alt="Krosno Toolshed
Supabase-53F3849B-2D86-494B-BE25-8D23EA050243"
src="https://github.com/user-attachments/assets/7bd2e9a6-82ae-48a1-9ef1-591b7a33632e"
/> |
## What is the new behavior?
- We use the _Claude_ logo for _Claude Code_
- Removed duplicative logos
- Made note of which MCP servers have a different logo for dark mode
## What kind of change does this PR introduce?
UI fix
## What is the current behavior?
Radio button circles are off-center in Safari.
## What is the new behavior?
Radio button circles are centered in Safari. Extraneous stroke on the
Lucide Circle icon also removed.
| Before | After |
| --- | --- |
| <img width="1502" height="864" alt="General Supabase"
src="https://github.com/user-attachments/assets/7fea0cc5-d62f-4c29-b341-494e66b91c38"
/> | <img width="1502" height="864" alt="General Supabase"
src="https://github.com/user-attachments/assets/296cbb72-ced2-44f7-8c73-d2c758a66507"
/> |
It’s hard to see the before-after via screenshots. Go to org settings on
`master` in Safari to see the difference.
## Additional context
We already applied this fix in `radio-group-stacked`.
## 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?
- Allow selecting the column, it respects different types and updates
the values correctly. If the values are different it gets wiped due to
mismatches
- Updated E2E tests and unit tests
Adds the new `dedicated_pooler` entitlement and it's respective
entitlement checks in the following components: `ConnectTabContent`,
`ConnectStepsSection`, `LogsSidebarMenuV2` and `ConnectionPooling`
## Testing
### ConnectTabContent and ConnectStepsSection
- Head to `project/_?showConnect=true` with an Org on the Pro Plan or
above
- Assert that the `Dedicated Pooler` option is available.
<img width="1007" height="641" alt="image"
src="https://github.com/user-attachments/assets/b4891544-b84b-4745-9e25-4cbc7c76686c"
/>
### IPv4SidePanel
- Head to `/project/_/database/settings` with an Org on the Pro Plan and
above and assert that the Dedicated Pooler is available
<img width="889" height="562" alt="image"
src="https://github.com/user-attachments/assets/3150cb3d-18e9-4b34-bc9b-2589d0a33c5f"
/>
### Dedicated Pooler Logs
- Head to `/project/_/logs/dedicated-pooler-logs` with an Org on the Pro
Plan and assert that you are in the `dedicated-poolers-logs` page.
- Head to `/project/_/logs/dedicated-pooler-logs` with an Org on the
Free Plan and assert that you are redirected to `/logs/pooler-logs`
### Logs Sidebar
- Head to `/project/jdvjfujajfyywbaaakje/logs/explorer` with an Org on
the Free Plan
- Assert that only the "Poolers" collection is shown
- Head to `/project/jdvjfujajfyywbaaakje/logs/explorer` with an Org on
the Pro Plan
- Assert that the Dedicated and Shared Poolers collections are shown
<img width="251" height="774" alt="image"
src="https://github.com/user-attachments/assets/747bceee-d5e7-4a8f-911d-6b02cdb115eb"
/>
## 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 filters experience, we are missing null changes for dates
and also no support for isNull
- Updated E2E tests to account for new null cases
## Summary
- Add contest rules legal page (`/go/contest-rules`) with official
sweepstakes rules
- Add executive dinner landing page (`/go/stripe/exec-dinner`) with RSVP
form backed by HubSpot and Customer.io
- Add executive dinner thank-you page
(`/go/stripe/exec-dinner/thank-you`)
- Add Stripe Sessions contest page (`/go/stripe/contest`) for iPhone 17
Pro Max sweepstakes
## Notes
- HubSpot `formGuid` on the exec dinner page needs to be replaced with
the real value before going live
- Customer.io `staticProperties` support is needed to send `event_name`
as a track property (see TODO comment in exec dinner page)
- iPhone image placed at
`public/images/landing-pages/stripe-sessions/iphone17-pro-max.png`
## Test plan
- [ ] Verify all four pages render correctly at their respective slugs
- [ ] Test RSVP form submission on exec dinner page
- [ ] Confirm contest rules page content matches official legal rules
- [ ] Verify iPhone image renders in contest page hero
- [ ] Check mobile responsiveness on all pages
---------
Co-authored-by: Alan Daniel <stylesshjs@gmail.com>