Commit Graph
130 Commits
Author SHA1 Message Date
Pamela Chia 013af4ed58 feat(www): homepage json-ld, canonical, 404 links (#49533)
An agent-readiness scan of supabase.com (is-agentic.com, public report)
flagged that the homepage serves no structured data and no canonical tag
in raw HTML, and that the 404 page gives crawlers and agents no recovery
path. I fixed both.

**Changed:**
- **Homepage structured data**: the raw HTML now carries Organization
and WebSite JSON-LD plus `<link rel="canonical"
href="https://supabase.com">`. The schema builders already existed in
`lib/json-ld.ts` but were never wired to any page; this reuses the exact
inline-script pattern from the blog post pages. The canonical is
hardcoded to the production origin on purpose: `SITE_ORIGIN` resolves to
the branch URL on previews.
- **404 recovery links**: the 404 body now links to the docs, the
sitemap, and llms.txt, so a dead URL leads somewhere instead of a dead
end. The decorative giant "404" backdrop is a `div` instead of a second
`h1`, marked `aria-hidden`, and gets `pointer-events-none`: browser
testing showed the absolutely positioned backdrop was silently
swallowing clicks on the new links (positioned elements paint above
static siblings for hit-testing even when visually behind).
- **Drift-guard test**: `md-alternates.test.ts` asserted the literal
one-liner `alternates: mdAlternates('<slug>')`, which the canonical
wrapper breaks. I broadened the assertion to accept the spread shape
too; the rule it guards (every markdown-served slug advertises its `.md`
sibling) is unchanged and still enforced.

## To test
Tested locally against the dev server:
- [x] `curl -s localhost:3000` and parse the two `application/ld+json`
blocks: both valid JSON, types Organization and WebSite
- [x] `curl -s localhost:3000 | grep canonical`: expect `<link
rel="canonical" href="https://supabase.com"/>`, with the existing
`text/markdown` alternate link still present
- [x] `curl -s localhost:3000/some-nonexistent-page`: expect HTTP 404
with hrefs to `/docs`, `/sitemap.xml`, `/llms.txt` and exactly one
`<h1>` in the body

On the Vercel preview (verified via curl + Playwright browser run):
- [x] View source on the preview homepage: the two JSON-LD blocks
present and a canonical pointing at `https://supabase.com` (prod origin,
even on the preview host)
- [x] Open a nonexistent preview URL: 404 page renders the new link row
under the "Head back" button, visually unchanged otherwise (screenshots
in session records)
- [x] Added: click each recovery link: element hit-testing returns the
anchor for all three, and clicking Sitemap navigates to a valid
`/sitemap.xml` document (this check caught the pointer-events
regression, fixed in this PR)

## Linear
- Part of GROWTH-1124 (kept open: remaining scan findings are tracked in
a sub-issue)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **SEO & Discoverability**
- Added canonical URL metadata and structured organization and website
information to the homepage.
- Improved 404 page navigation with links to Documentation, Sitemap, and
`llms.txt`.

- **Accessibility**
- Updated the 404 page’s decorative background marker to be
non-interactive and hidden from screen readers.
  - Added reduced-motion handling for page transitions.

- **Tests**
- Updated metadata validation to support multiple alternate metadata
configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-26 16:41:46 +08:00
claude[bot]andClaude 580af6e336 fix(www): stop blog tag and author breadcrumbs from becoming the page h1 (#49507)
<!-- ccr-slack-attribution -->
_Requested by **Pam Chia** · [Slack
thread](https://supabase.slack.com/archives/C07P3AU3J2D/p1787616624076769)_

**Before:** searching "supabase blog" on Google surfaces blog tag
sitelinks titled `Blog/Tags/Supabase` and `Blog/Tags/Community`, each
with the same snippet scraped from the footer newsletter form ("Get
product updates and news from Supabase").

**After:** those results use the route's real title, `Blog | Supabase`,
with a description specific to the tag, for example "Blog posts tagged
Supabase."

This change stops the visible breadcrumb on blog tag and author pages
from being the page's only `<h1>`, and gives tag and category pages
distinct meta descriptions.

## How this changes the Google result

The bad sitelinks come from two independent mechanisms, and each half of
this PR targets one of them:

**Titles.** Google prefers a page's `<h1>` over its `<title>` when the
two disagree, and on tag pages the only `<h1>` is the breadcrumb, whose
textContent is exactly `Blog/Tags/Supabase` (JSX strips the whitespace
between the children). Demoting the breadcrumb to a `<nav>` removes the
conflicting heading, so Google should fall back to the route's real
`<title>`:

- `Blog/Tags/Supabase` becomes `Blog | Supabase`
- `Blog/Tags/Community` becomes `Blog | Community`

**Snippets.** The "Get product updates and news from Supabase. Subscribe
..." text is not a meta description; it is Google's own synthesized
snippet, scraped from the footer newsletter form. Every tag and category
page shipped the byte-identical description "Latest news from the
Supabase team.", and Google discards a description duplicated across
many URLs. With a unique per-page description, Google has a usable
candidate again:

- tag rows should show `Blog posts tagged Supabase.` / `Blog posts
tagged Community.`
- category rows (`Blog | Engineering`, `Blog | Product`) already had
correct titles but the same scraped snippet; they should now show `Blog
posts in Engineering.` / `Blog posts in Product.`

Two caveats. Meta descriptions are suggestions, not directives, so
Google can still synthesize its own snippet; removing the
duplicate-description cause makes the supplied one much more likely to
win, but does not force it. And the replacement `<h1>` is the constant
sr-only `Supabase Blog` on every listing page: if Google again prefers
the h1 over the title, all sitelinks would read `Supabase Blog`. A
page-specific heading ("Posts tagged Supabase", "Posts by <author>")
would eliminate that residual risk and is a candidate follow-up.

Neither change appears in search results until Google recrawls and
reprocesses these URLs (see Additional context; the tag routes are
absent from the sitemap, which slows this). Requesting reindexing of a
few of these URLs in Search Console would speed it up.

## 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?

Bug fix (SEO / accessibility), `apps/www` only.

## What is the current behavior?

Two separate defects feed the same bad search result.

Google prefers a page's `<h1>` over its `<title>` when the two disagree,
and on tag pages the only `<h1>` is the breadcrumb.
`apps/www/app/blog/tags/[tag]/TagClient.tsx:21-27` wraps `Blog` / `/` /
`Tags` / `/` / `<tag>` in an `<h1>`; JSX strips the whitespace between
those children, so the element's textContent is exactly
`Blog/Tags/Supabase`. The route's own `<title>` is already fine
(`apps/www/app/blog/tags/[tag]/page.tsx:26`).
`apps/www/app/blog/authors/[author]/AuthorClient.tsx:55-60` has the
identical defect. Category pages escape it because
`apps/www/app/blog/BlogLayoutShell.tsx:19` counts `/blog/categories/` as
a listing route and renders the sr-only `<h1>Supabase Blog</h1>` at line
23, while `CategoryClient.tsx` renders no `<h1>` of its own.

Separately, every tag and category page shipped the byte-identical
description `Latest news from the Supabase team.`
(`apps/www/app/blog/tags/[tag]/page.tsx:27`,
`apps/www/app/blog/categories/[category]/page.tsx:23`). Google discards
a description reused verbatim across many pages and generates its own
snippet, in this case from the footer newsletter copy at
`apps/www/components/Footer/index.tsx:179`.

## What is the new behavior?

- `BlogLayoutShell.tsx` — `isListingRoute` now covers `/blog/tags/` and
`/blog/authors/` alongside `/blog/categories/`, via a
`LISTING_ROUTE_PREFIXES` constant. Those routes now render the same
sr-only `<h1>Supabase Blog</h1>` category pages already had.
- `TagClient.tsx` and `AuthorClient.tsx` — the breadcrumb is now a `<nav
aria-label="Breadcrumb">` instead of an `<h1>`. Every existing
className, the `/` separator spans and their `px-2` padding are
unchanged. The `h1` element selector in
`apps/www/styles/globals.css:176-179` applies `font-heading font-medium
tracking-normal`, so those three utilities move onto the `nav` to keep
the rendering byte-identical. No visual change is intended; only the
element and its accessible role change.
- `tags/[tag]/page.tsx` and `categories/[category]/page.tsx` —
`generateMetadata` now returns `Blog posts tagged ${label}.` and `Blog
posts in ${label}.`, matching the shape the author route already uses
(`apps/www/app/blog/authors/[author]/page.tsx:37`). Both use `startCase`
from `apps/www/lib/helpers.tsx:75-81` rather than `capitalize`, so
`launch-week` reads "Launch Week" and matches the filter chip label at
`apps/www/components/Blog/BlogFilters.tsx:56-57`. Title and description
use the same label.

## Additional context

`apps/www` is owned by `@supabase/marketing` per
`.github/CODEOWNERS:13`, so marketing should review this.

Recovery is not immediate: Google has to recrawl these routes before the
corrected titles and descriptions show up in search results.

Noted follow-ups, deliberately out of scope here:

- `/blog/tags/*` and `/blog/authors/*` are absent from the generated
sitemap (`apps/www/internals/generate-sitemap.mjs`), which slows
discovery and recrawl.
- The page bodies still pass a `capitalize`-derived label to `TagClient`
and `CategoryClient`, so the visible tag breadcrumb reads "Launch week"
while the title now reads "Launch Week". Aligning the visible label
would be a rendered-text change, so it is left for a separate PR.
- `openGraph` metadata on these routes is untouched and still carries
the generic copy.

### How it was tested

Prettier passes on the five changed files with the repo config, in both
the default and the `SORT_IMPORTS=false` mode CI uses. Full typecheck
and lint could not be run in this environment (no `node_modules`); the
changes are type-trivial — a `string[]`.`some()` predicate, a JSX tag
swap, and two template literals over an existing exported
`startCase(string): string` helper — and the diff parses clean under
`tsc` with module resolution disabled. Worth a reviewer eyeballing the
tag and author pages side by side against production to confirm the
breadcrumb renders identically.


---
_Generated by [Claude
Code](https://claude.ai/code/session_0164goAzGTkGnoxzCKagJ3Hw)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-25 14:44:58 +08:00
Miranda LimonczenkoandClaude Opus 5 60f7903b52 fix(www): group the filter controls and announce the result count (#49410)
Closes FE-4251

## Problem

The filter sidebars are unstructured `div` nesting. Measured on a
preview:

* 9 checkboxes on `/features` and 13 on `/partners/catalog`, none inside
a `fieldset`, a `role="group"`, or any region.
* The `/features` "Filter by tags:" `h2` has no `id`, so nothing can
reference it as a group name.
* The only landmarks on `/features` are two `nav` elements, so the
filter panel is unreachable by landmark navigation.

A screen reader user meets a checkbox announced as "authentication,
checkbox" with nothing conveying that it filters features by tag.

Separately, both result counts update on every filter change with no
live region, so the outcome of toggling a filter is never announced.

## Solution

* Wrap each checkbox set in a labelled `role="group"`.
* Wrap each filter panel in an `aside` labelled "Filters".
* Add `aria-live="polite"` to both result counts.

The two pages name their group differently on purpose. `/features` uses
`aria-labelledby` pointing at the existing `h2`, so the visible heading
is the accessible name. `/partners/catalog` uses `aria-label`, because
`filtersPanel` renders into both the desktop sidebar and the mobile
sheet, so an `id` would appear twice in the DOM. That file already calls
out the duplicate-id hazard at line 152 as its reason for using wrapping
labels.

Chose `role="group"` over `fieldset` and `legend` to avoid resetting UA
styling in a styled sidebar.

The single self-hosted checkbox keeps its own label and needs no group.

## Manual testing

**/features**

1. Open
[/features](https://zone-www-dot-com-git-www-filter-groups-and-live-count-supabase.vercel.app/features)
with Screenreader.
2. Confirm the tag checkboxes report as a group named "Filter by tags:".
3. Confirm a "Filters" landmark appears in landmark navigation.
4. Tick a tag filter. The result count changes and is announced.

**/partners/catalog**

5. Open
[/partners/catalog](https://zone-www-dot-com-git-www-filter-groups-and-live-count-supabase.vercel.app/partners/catalog)
at a desktop width. The filter panel is `hidden md:block`, so the
landmark only exists at md and above.
6. Confirm the category checkboxes report as a group named "Categories".
7. Open the mobile filter sheet at a narrow width and confirm the group
is still named, with no duplicate ids.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility Improvements**
* Improved screen reader navigation for partner catalog and feature
filters.
  * Added accessible labels and landmarks for filter sections.
  * Updated result counts to be announced when selections change.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:46:03 -07:00
Miranda LimonczenkoandClaude Opus 5 0243ad7cf1 fix(www): make the view toggles a radio group and fix the filter rows (#49346)
Closes FE-4227

> [!NOTE]
> Bottom of a stack. #49409 and #49410 sit on top of this one, so merge
this first.

## Problem

Five defects in the view toggles on `/features` and `/partners/catalog`,
plus one in the `/features` filter rows. All measured on a preview.

**Toggles**

| Defect | Evidence |
| -- | -- |
| No pointer cursor | Tailwind 4 Preflight no longer sets `cursor:
pointer` on buttons. 14 of 19 buttons on `/features` computed to
`default`. Anchors were unaffected, which is why it looked inconsistent
rather than total. |
| The selected toggle offered a pointer | It is a no-op, so the cursor
promised an action that does nothing. |
| The selected state was invisible in light mode | `bg-surface-300` and
`bg-surface-75` both resolve to pure white. Contrast ratio exactly
1.000. The light theme base lightness is `.995` and each surface step
adds `.024`, so every lighter step clamps at white. The only cue left
was icon colour. |
| Hover inverted the selection | Unselected hover is `bg-surface-200`, a
2.7% black overlay, while the selected state was white. Hovering the
wrong button made it look selected. |
| No grouping | Two unrelated buttons. Nothing conveyed one choice with
two options, and the selected view was not programmatically determinable
at all. |

**Filter rows on /features**

A pointer appeared only on the narrow gap between each checkbox and its
label:

| Element | Computed cursor |
| -- | -- |
| wrapper `div` | `pointer` |
| `label` | `default` |
| checkbox | `default` |

`cursor-pointer!` sat on the wrapper. A declaration targeting an element
always beats an inherited value, so `!important` on the parent changed
nothing and both children overrode it.

## Solution

**Toggles become a `ToggleGroup`** on both pages, replacing the raw
button pairs.

* `type="single"` renders `role="group"` with `role="radio"` and
`aria-checked` per item. That describes one choice with two options
rather than two independent toggles, so a screen reader announces the
selection and its position in the set.
* Each group gets an `aria-label`, which the existing `ToggleGroup`
usage on `/pricing` lacks.
* Selected item gets `cursor-default`, unselected gets `cursor-pointer`.
* Selected background becomes `bg-surface-400`, a 5.4% overlay that
clears the 2.7% unselected hover and removes the inversion.

**Filter rows** become wrapping `label` elements with `cursor-pointer`
directly on the label, matching `IntegrationsContent.tsx`. The whole row
becomes a click target, and `id` values derived from raw product names
go away.

`toggleVariants` sets the selected background to `bg-surface-300` under
both `data-[state=on]:` and `aria-checked:`, and twMerge only dedupes
matching prefixes. Both are overridden here so adopting the primitive
does not reintroduce the invisible state this PR fixes. The primitive
defect is FE-4245.

### Behaviour change

The toggle pair is now a single tab stop navigated with arrow keys,
rather than two separate tab stops. That is correct for a mutually
exclusive group, but it is a change from current behaviour.

### Related, deliberately not here

| Work | Where |
| -- | -- |
| Checkbox primitive pointer cursor | #49408, so the shared-package
change is reviewed separately. The checkbox itself still shows an arrow
on this branch. |
| Naming these toggles, which rely on `title` | FE-4229 |
| Base-layer cursor fix across www, Docs and Studio | FE-4228 |
| Sharing one component between the two pages | FE-4244 |

## Manual testing

1. Open
[/features](https://zone-www-dot-com-git-www-view-toggle-pointer-cursor-supabase.vercel.app/features)
in light mode. The selected toggle is visibly darker than the unselected
one.
2. Hover the selected toggle. The cursor is an arrow. Hover the
unselected one. It is a pointer, and it does not become darker than the
selected one.
3. Tab to the toggle pair. It takes one tab stop. Move between options
with the arrow keys.
4. Inspect either toggle. It has `role="radio"` with `aria-checked`
tracking the selection, and the wrapping group has an `aria-label`.
5. Hover a tag filter row over the label text and over the gap between
the checkbox and the text. Both show a pointer. The checkbox itself
still shows an arrow here; that is #49408.
6. Click a filter row well away from the checkbox. The filter toggles.
7. Repeat steps 1 to 4 on
[/partners/catalog](https://zone-www-dot-com-git-www-view-toggle-pointer-cursor-supabase.vercel.app/partners/catalog).

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:19:59 -07:00
Miranda LimonczenkoandClaude Opus 5 c79d7be7d9 fix(www): give the feature and partner card grids list semantics (#49411)
Closes FE-4252

## Problem

`/features` renders 79 feature cards as bare `Link` elements in a grid
`div`. Measured on a preview, `main` contains zero `ul`, `ol`, `li`, and
zero `role="list"`. `/partners/catalog` is the same.

A screen reader user gets a run of loose links with no "list, 79 items",
no set size, and no way to navigate by list. Sighted users see an
obvious grid of cards, and the structure conveying that is purely
visual.

Same defect class as FE-4101 and DOCS-1279, both already in this
milestone.

## Solution

Make each card container a `ul` with one `li` per card. Four containers:

| File | Container |
| -- | -- |
| `apps/www/pages/features.tsx` | feature card grid |
| `apps/www/app/partners/catalog/IntegrationsContent.tsx` | featured
partners grid |
| same | grid view |
| same | list view |

This change makes a Screenreader announce the number of items and track
them.

Most of this diff is re-indentation from the added wrapper.

## Manual testing

**/features**

1. Open
[/features](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/features)
with Screenreader. Confirm the cards report as a list of 79 items, and
that the count tracks the filters.
2. Check the grid at mobile, tablet and desktop widths. Cards stay equal
height within a row and the column counts are unchanged.

**/partners/catalog**

3. Open
[/partners/catalog](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/partners/catalog)
in grid view with Screenreader. Confirm both the featured section and
the main grid are lists.
4. Switch to [list
view](https://zone-www-dot-com-git-www-card-grid-list-semantics-supabase.vercel.app/partners/catalog?view=list).
Confirm it is a list and the dividing lines between rows are unchanged.

Compare any of these against
[production](https://supabase.com/features). The rendering should be
identical; only the markup changes.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility**
* Improved semantic structure for partner catalog and feature cards
using properly organized lists.
* Expanded card links to make larger portions of featured and grid cards
clickable.
  * Preserved existing layouts, content, and filtering behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:19:40 -07:00
Miranda LimonczenkoandClaude Opus 5 932180541e fix(ui-patterns): give the shared InfoTooltip trigger an accessible name (#49345)
Closes FE-4093

## Problem

The shared `InfoTooltip` trigger's only child is an SVG and it has no
accessible name, so a screen reader announces an unnamed button and the
information the tooltip carries is unreachable. `button-name`, critical.

`/pricing` renders 34 of them.

## Solution

* Add an optional `label` prop rendered as `sr-only` text, with a
generic fallback so the 22 call sites that pass nothing still get a
name. The prop is optional because 26 files import this component across
www, Studio, design-system and ui-patterns.
* Drop the redundant `role="button"` from a native button.
* Label the four www call sites. A shared fallback alone would leave
`/pricing` announcing 34 identical names, which passes axe and stays
unusable. The labels come from the feature title and plan already in
scope, so no pricing data changes.

Docs is unaffected. It has its own `InfoTooltip` at
`apps/docs/features/ui/InfoTooltip.tsx` and never imports the shared
one.

## Manual testing

1. Open
[/pricing](https://zone-www-dot-com-git-ui-patterns-infotooltip-ac-07e2ab-supabase.vercel.app/pricing)
using a Screenreader.
2. Tab through the comparison table. Each info tooltip announces its own
feature, for example "About Database size".
3. Tab to a plan-specific tooltip. It announces the feature and the
plan, for example "About Automatic backups on the pro plan".
4. Confirm the icons render unchanged and the tooltips still open on
hover and on focus.
5. Run axe on the page. `button-name` reports zero elements.
6. Open the [design system InfoTooltip
page](https://design-system-git-ui-patterns-infotooltip-acces-66ec02-supabase.vercel.app/design-system/docs/fragments/info-tooltip)
and confirm the demo still renders.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Accessibility Improvements**
  * Added descriptive labels to pricing information tooltips.
* Improved screen reader context for compute estimates, features, and
plan-specific pricing.
  * Added a default “More information” label for unlabeled tooltips.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:14:12 -07:00
Danny White fdf33e72c4 fix(studio): clean up onboarding returnTo paths (#49283)
## What kind of change does this PR introduce?

Bug fix. Follow-up to #41041 and DEPR-318.

## What is the current behavior?

Marketing "Start your project" links go to `/dashboard`, which redirects
unauthenticated users to `/org` and sets `returnTo=/org`. That value
survives when they switch from sign-in to sign-up, so email verification
still lands on the org list instead of org creation.

## What is the new behavior?

- Sign-in's **Sign up** link rewrites `returnTo=/org` (and
`/organizations`) to `/new`
- Docs mobile menu, www homepage/product CTAs, and solution page CTAs
link to `/dashboard/sign-up` for guests
- Signed-in visitors get the dashboard URL instead, so they never hit
the sign-up form
- Shared `DASHBOARD_SIGN_UP_URL` / `getDashboardCtaHref` helpers for www

Stacked on #41041.

## To test

Stacked on #41041. The studio preview below includes both PRs. www and
docs have their own previews.

### Studio: sign-in → sign-up rewrite

Using the [studio-staging
preview](https://studio-staging-git-dnywh-fixonboarding-return-to-supabase.vercel.app/)
from Vercel checks:

1. Open the preview while logged out. It should land on
`/dashboard/sign-in?returnTo=%2Forg`
2. Click **Sign up**. Expect the URL to include `returnTo=%2Fnew`

### Optional: www CTAs

Using the [www
preview](https://zone-www-dot-com-git-dnywh-fixonboarding-return-to-supabase.vercel.app/):

3. Logged out: homepage, product, or solutions **Start your project**
should go to `/dashboard/sign-up`
4. Logged in: the same CTAs should go to `/dashboard` (not sign-up)
(thought this will be hard if not impossible to test on staging)

### Optional: docs CTAs

Using the [docs
preview](https://docs-git-dnywh-fixonboarding-return-to-supabase.vercel.app/):

5. On mobile nav while logged out, click **Start your project**. Expect
`/dashboard/sign-up`

### Compare on supabase.green

Optional. Just to show what happens currently on `master`:

6. Open **supabase.green** while logged out, then click **Sign up** from
`/dashboard/sign-in?returnTo=%2Forg`. `returnTo` should stay as `/org`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Start-project and sign-up links now direct visitors to registration
while signed-in users continue to reach the dashboard.
* Homepage, product, solution, and mobile navigation CTAs now provide
consistent authentication-aware destinations.
* Sign-up links preserve return destinations and existing navigation
parameters.

* **Bug Fixes**
* Corrected mobile navigation and marketing CTA links that previously
sent visitors to the dashboard root instead of the appropriate sign-up
flow.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 17:32:56 +10:00
Pamela Chia 21a27eeb4f feat(www): canonicalize homepage markdown at /index.md (#49384)
The www root markdown lived at an accidental URL: `/.md` served the
homepage markdown only because middleware strips the `.md` suffix and
the empty slug fell through to the homepage allowlist entry, while the
canonical-looking `/index.md` 404'd. The served markdown also opened
with stale legacy positioning copy that no longer matches the site. I
renamed the homepage content slug to `index` end-to-end so `/index.md`
is the one canonical markdown URL.

**Changed:**
- **`/index.md` serves the homepage markdown (200 `text/markdown`)**:
`content/md/homepage.md` renamed to `index.md`; the middleware bare-root
slug mapping, the generator's sort special-case, and the homepage
alternate tag follow, so the tag now advertises `/index.md`.
- **Legacy aliases 308 to the canonical URL**: `/.md`, `/homepage.md`,
and bare `/index` redirect via `lib/redirects.js`; `/llms/homepage.txt`
retargeted straight to `/index.md` to avoid a redirect chain. New
`next.config.test.ts` assertions pin all four.
- **Positioning refreshed**: the markdown now opens with "Supabase is
the Postgres development platform" (matching the site title), replacing
the outdated tagline.
- **Generator safety**: the redirect-exclusion filter in
`generateMdContent.mjs` now exempts the `index` slug (its HTML page is
`/`, not `/index`, so a `/index` redirect never refers to it), and the
build fails if `content/md/index.md` ever goes missing while middleware
still maps `/` to the `index` slug.
- **CI actually runs the new assertions**: I widened the `www-tests.yml`
paths filter to include `apps/www/lib/**/*.js`,
`apps/www/content/md/**`, and `apps/www/scripts/**/*.mjs`. It previously
only matched `.ts*` and the next.config files, so a PR touching only
`lib/redirects.js`, the markdown content, or the generator would skip
the tests that pin these redirects.

**Note:** the existing homepage alternate tag still exists, re-pointed
to the canonical URL. Whether the homepage should advertise a markdown
sibling at all is a separate decision; leaving it aimed at a 308 would
break tag consumers. Positioning wording is editorial, happy to tweak.

## To test
Tested on Vercel preview:
- [x] `curl -si <preview>/index.md`: expect 200 `content-type:
text/markdown`, body opens with the Postgres development platform
positioning and no longer contains the old tagline
- [x] `curl -sI <preview>/.md`: expect 308 with `location: /index.md`
- [x] `curl -sI <preview>/homepage.md` and `curl -sI
<preview>/llms/homepage.txt`: expect 308 with `location: /index.md`
- [x] `curl -sI <preview>/index`: expect 308 with `location: /`
- [x] `curl -s -H "Accept: text/markdown" -o /dev/null -w "%{http_code}
%{content_type}" <preview>/`: expect `200 text/markdown` (bare-URL
negotiation unchanged)
- [x] `curl -s <preview>/ | grep -o 'type="text/markdown"
href="[^"]*"'`: expect href ending `/index.md`

## Linear
- fixes GROWTH-1117



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added support for `/index.md` as the canonical Markdown representation
of the homepage.
- Added permanent redirects for legacy homepage Markdown and text URLs.
  - Added `/index` to `/` redirect handling.

- **Bug Fixes**
- Updated homepage metadata, alternate links, Markdown negotiation, and
content generation to consistently use the new canonical path.
  - Improved homepage content description.

- **Tests**
- Expanded coverage for homepage Markdown routes, redirects, and URL
matching.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 15:19:56 +08:00
Pamela Chia 10c425ad0b feat(www): markdown copy/ask affordances (#48475) 2026-08-21 08:51:11 +08:00
Etienne Stalmans 18dc7e971d chore: update vendor DepthFirst (#49093) 2026-08-14 14:27:44 +08:00
claude[bot]andClaude c30437a58a fix: use shared favicon metadata so the tab icon isn't blurry on hi-dpi (#48770)
<!-- ccr-slack-attribution -->
_Requested by **Matt Rossman, Ali Waseem** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1785960993618839?thread_ts=1785960993.618839&cid=C0161K73J1J)_

## 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?

Bug fix.

## What is the current behavior?

The Supabase logo in the browser tab looks blurry on high-DPI displays
on supabase.com, but sharp on the dashboard. Same logo, same asset files
— only the marketing site looks soft.

Separately, `genFaviconData()` points one of its `<link rel="icon">`
tags at `favicon-128x128.png`, a file that no app in the repo ships.
That is a live 404 on docs, learn and ui-library today — and on
design-system, which hardcodes its own copy of the same icon list.

## What is the new behavior?

The tab icon is sharp on both, and the 404 is gone everywhere.

## Additional context

**How.** `apps/www/app/layout.tsx` hardcoded a Next.js `metadata.icons`
block that pointed `icon`, `shortcut` and `apple` all at
`/favicon/favicon.ico`. That `.ico` contains a single 16x16 layer, so on
a 2x display the browser has no 32px candidate to choose and upscales
the 16x16 — hence the blur. It only affects App Router routes, which now
includes the homepage, `/blog`, `/pricing` and the product pages; www's
remaining Pages Router routes already went through the shared component
and were fine.

www was not using the shared `genFaviconData()` helper from
`common/MetaFavicons/app-router`, which docs, learn and ui-library all
do. Swapping it in makes www advertise the same 16/32/48/96/128/180/196
PNG ladder the dashboard does, so the browser picks the 32px PNG on a 2x
display. The argument is `''` because www serves from the site root
(`basePath: ''` in `next.config.mjs`).

**Second, related change.** `packages/common/MetaFavicons/app-router.ts`
referenced `favicon-128x128.png`; the asset is `favicon-128.png` in
every app's `public/favicon/` (the pages-router variant of the helper
already had it right). Fixed to match. Without this, wiring www up to
the helper would have added a fourth app to the existing 404.

**Third, related change.** `apps/design-system/app/layout.tsx` had its
own inline copy of `genFaviconData` — byte-identical to the shared one
except that it still pointed at `favicon-128x128.png`, so fixing the
shared helper alone would have left design-system 404ing. Replaced the
91-line inline copy with the shared import, passing the app's existing
`BASE_PATH` (which mirrors `basePath` in its `next.config.mjs`) the same
way docs, learn and ui-library do. That removes the last hardcoded icon
list among the App Router apps, so the filename can't drift back out of
sync.

No favicon image assets were added or changed — every file the helper
references already exists in both `apps/www/public/favicon/` and
`apps/design-system/public/favicon/`.

**Possible follow-up.** `favicon.ico` itself is single-layer 16x16 in
both www and studio (byte-identical files). Regenerating it as a
multi-resolution ICO with 16/32/48 layers would help any consumer that
only reads the `.ico` — bookmark bars, some browser surfaces, and
notably supabase.com/evals, which is a rewrite to a separate Vercel app
and so won't pick up this layout change, but does resolve root-relative
icon hrefs against www's `public/`. Left out here because it touches
studio's assets too and is a separate call.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01F2AZs625JxKASYVAj8LWYq)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-14 10:55:49 +08:00
Shane c23f94cda3 Update homepage customer stories (#48955)
## 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?

Update to customer stories section on www

## What is the current behavior?

Please link any relevant issues here.

## What is the new behavior?

<img width="1021" height="691" alt="Screenshot 2026-08-11 at 3 23 03 PM"
src="https://github.com/user-attachments/assets/ee44f874-1cdf-47d6-bb63-6cdd8f85563a"
/>
<img width="1016" height="661" alt="Screenshot 2026-08-11 at 3 23 09 PM"
src="https://github.com/user-attachments/assets/97e84189-4351-489f-831f-f938a461e1dd"
/>
<img width="1011" height="661" alt="Screenshot 2026-08-11 at 3 23 13 PM"
src="https://github.com/user-attachments/assets/48ebdb06-6d6d-4711-ae5e-31cd513b144b"
/>
<img width="1036" height="677" alt="Screenshot 2026-08-11 at 3 23 17 PM"
src="https://github.com/user-attachments/assets/576aae48-33a3-4fe0-bc71-e6a0e3342608"
/>
<img width="1025" height="690" alt="Screenshot 2026-08-11 at 3 23 20 PM"
src="https://github.com/user-attachments/assets/5b7616f7-e968-4cbf-bd18-67de73904f14"
/>

## Additional context

Add any other context or screenshots.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Content Updates**
* Refreshed the customer stories section with new featured companies,
testimonials, icons, colors, and visual gradients.

* **Responsive Design**
* Updated the layout breakpoint to improve the transition between mobile
and desktop presentations.
* Improved icon rendering with optional scaling for better visual
balance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-12 09:34:56 -05:00
Danny White 2e7a8a3362 chore(www): rename customer logo folders to on-dark and on-light (#48962)
## What kind of change does this PR introduce?

Chore: rename customer logo folders and document the theme contract. No
intended visual change, aside from Phoenix Energy whose two marks were
in the wrong folders.

## What is the current behavior?

Customer logos live at:

- `/images/customers/logos/{slug}.png` (`logo`, light mode)
- `/images/customers/logos/light/{slug}.png` (`logo_inverse`, dark mode)

`light/` actually means “use me on a dark background”.

## What is the new behavior?

Same assets, clearer paths:

- `/images/customers/logos/on-light/{slug}.png` → dark/black mark →
`logo` → light mode
- `/images/customers/logos/on-dark/{slug}.png` → light/white mark →
`logo_inverse` → dark mode

Icon chips stay at `/images/customers/logos/{slug}-icon.svg`. Old
`/images/customers/logos/light/*` URLs redirect to `on-dark`. www README
now has the contract.

# To test

Use the [www
preview](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app).
Toggle light/dark from the site header on each page. Logos should stay
readable (no white-on-white or black-on-black).

1. [Customers
grid](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/customers)
— main `logo` / `logo_inverse` surface. Spot-check Juniver, Phoenix
Energy, and one other card.
2. [Phoenix Energy
story](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/customers/phoenix-energy)
— story header uses `logo` only (on-light, plus a dark-mode brightness
filter). We swapped this pair.
3.
[Homepage](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/)
— “How industry leaders…” section. Icon chips only (`*-icon.svg`); the
wordmark `logo` field is unused here.
4. [Solutions /
Agents](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/agents)
— Chatbase quote near the top shows both theme variants. Same pattern on
[/healthcare](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/healthcare),
[/finserv](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/finserv),
and
[/b2b-saas](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/b2b-saas).
5. [Contact
sales](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/contact/sales)
— Good Tape / Xendit / Chatbase wordmarks (`on-light`). Same logos on
the demo form at
[/solutions/enterprise](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/enterprise).
6.
[Enterprise](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/solutions/enterprise)
— Mozilla / Epsilon3 / Pebblely icons in the use-cases section
(`on-dark`).
7.
[Vector](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/modules/vector)
— customer quotes. This is the only page that builds `on-light` /
`on-dark` paths at runtime from the customer slug.
8. [Mobbin
event](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/events/migrating-from-firebase-mobbin)
— company logo uses event `logo` / `logo_light` (dark vs light).
Optional second:
[/events/scale-to-millions-goodtape-auth](https://zone-www-dot-com-git-dnywh-chorecustomer-logo-o-0d7bc1-supabase.vercel.app/events/scale-to-millions-goodtape-auth).

Quick extra: hover **Product** in the site nav. The customer story
thumbnail uses `imgUrl` (`on-light`).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Documentation
- Clarified customer logo requirements, including separate light and
dark asset locations, monochrome formats, and dark PNG assets for image
generation.

## Updates
- Standardized customer logos across stories, events, sales pages,
solution pages, testimonials, and generated images.
- Improved logo rendering across light and dark themes with dedicated
variants.
- Added permanent redirects for legacy logo URLs while preserving
filename suffixes.

## Tests
- Added coverage verifying legacy logo redirects resolve correctly,
including supported exceptions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-12 03:49:21 +00:00
AnaandAna 3fdaf14b4e chore(www): update Edge Functions customer quote to eXp Realty (#48667)
## 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?

- Updates the customer testimonial on the Edge Functions product page

## What is the current behavior?

The Edge Functions page shows an older customer quote.

## What is the new behavior?

- The quote is from Seth Siegler, Chief Innovation Officer at eXp Realty
- The quote is taken verbatim from the published eXp Realty customer
story
- The attribution links to /customers/exprealty
- Uses the existing seth-siegler.jpg avatar already in the repo; no new
assets

## Additional context

N/A


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Content Updates**
* Updated the Edge Functions customer testimonial with a new quote,
customer attribution, profile image, role, and link.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ana <ana1337x@users.noreply.github.com>
2026-08-04 13:58:46 +07:00
Jonathan Summers-Muir 009528c6ca chore: update Lovable homepage logo (#48536)
## Summary

- replace the outdated Lovable homepage logo
2026-07-31 11:58:34 +00:00
Danny White 37dded67d1 feat: unify SkipToContent across studio, docs, www, and design-system (#48314)
## What kind of change does this PR introduce?

Feature / a11y polish

## What is the current behavior?

Studio and Docs each had their own skip-to-content link (different
styling and behaviour). www and design-system had none.

## What is the new behavior?

Shared `SkipToContent` in `ui-patterns`, adopted by Studio, Docs, www,
and design-system. Documented as a fragment with a short note under
Accessibility → Jumping ahead.

Tab once to reveal the button (top-left), Enter to jump to a
content-only `<main>`.

| After |
| --- |
| <img width="836" height="324" alt="CleanShot 2026-07-24 at 14 08
47@2x"
src="https://github.com/user-attachments/assets/6df29452-e53a-4eca-8f64-946f2b9f605d"
/> |

## To test

Shared steps for every app: enable Tab key navigation if needed, load
the preview, press **Tab** once — skip button should slide in top-left.
Press **Enter** — focus jumps to main content (no blue ring on
`<main>`). Press **Tab** again — first interactive control in the page
body, not the sidebar/nav. Hover the skip button — solid fill, clear
hover state, no chrome showing through.

- **Studio** —
[preview](https://studio-staging-git-dnywh-featskip-to-content-supabase.vercel.app)
→ sign in → any project page
- **Docs** —
[preview](https://docs-git-dnywh-featskip-to-content-supabase.vercel.app)
→ any docs page with sidebar
- **www** —
[preview](https://zone-www-dot-com-git-dnywh-featskip-to-content-supabase.vercel.app)
→ homepage or any marketing page with the default nav
- **Design system** —
[preview](https://design-system-git-dnywh-featskip-to-content-supabase.vercel.app)
→ any docs page (confirm Tab from content does **not** walk the
sidebar), plus [Skip to Content
fragment](https://design-system-git-dnywh-featskip-to-content-supabase.vercel.app/docs/fragments/skip-to-content)

## Additional context

Follow-up to #47694 / #48303 (Studio) and #47515 (Docs).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added a reusable “Skip to content” accessibility link across key
layouts and pages.
- Updated main landmarks to support keyboard focus and skip-link
navigation (`id="main"`).
- **Accessibility**
- Skip links now follow consistent landmark-target conventions and
remain hidden until focused.
- Improved documentation for skip links/jump shortcuts in persistent
chrome layouts.
- **Documentation**
- Added a dedicated Skip to Content fragment, navigation entry, and
expanded accessibility guidance.
  - Updated button description wording in component docs.
- **Tests**
  - Added component tests for SkipToContent.
- **Chores**
  - Exposed SkipToContent via additional public package entry points.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-29 06:21:50 +10:00
Alaister YoungandAlaister Young ca2b50a0a7 chore(ui-patterns): collapse the admonition shim into ui-patterns/Admonition (#48377)
Follow-up to #48344: collapses the two resolution paths for the
Admonition module into one.

`src/admonition.tsx` was a back-compat shim re-exporting
`src/Admonition/`. Two ways to resolve one module is exactly what
produced the macOS self-import bug fixed in #48344, and the local
typecheck errors that #48374 worked around. This removes the shim and
standardizes on the PascalCase subpath, matching every other export in
the package.

**Changed:**

- Codemodded all 246 `ui-patterns/admonition` imports to
`ui-patterns/Admonition` (240 `.tsx`, 5 `.mdx`, 1 `.ts` across studio,
docs, www, design-system, and lite-studio)
- Pointed the 5 internal `'../admonition'` imports back at the
`'../Admonition'` directory

**Removed:**

- `packages/ui-patterns/src/admonition.tsx`, and its `./admonition`
entry in the exports map (regenerated with `pnpm gen:exports`)

## To test

- `grep -r "ui-patterns/admonition" --include='*.ts*'` → no hits
- `pnpm test:case-hazards` → passes
- `pnpm typecheck` → all 15 tasks green
- `pnpm --filter studio run lint:ratchet` → passes
- `pnpm --filter ui-patterns vitest run src/Admonition` → 11 tests pass

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Standardized Admonition component imports across the application and
documentation.
* Improved compatibility with case-sensitive environments by using the
canonical component path.
  * Removed the legacy Admonition import entry point.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-29 00:48:56 +08:00
Pamela Chia 9113c2ba04 feat: markdown alternate tags + llms.txt cleanup (#48287)
The June/July marketing redesign (#47271, #47228) rebuilt the homepage
and product pages off the Pages Router, silently dropping their `<link
rel="alternate" type="text/markdown">` head tags, and llms-full.txt has
been accidentally embedding every blog/customer/event page via an
`MD_CONTENT` spread. I restored the tags behind a shared helper, added a
CI drift test so a future redesign can't drop them silently again, and
trimmed both llms files to the agreed docs-index shape.

**Changed:**

- **Markdown siblings advertised again**: homepage, the 5 product pages,
pricing, and blog emit absolute `.md` alternate URLs via a new
`mdAlternates(slug)` helper (the one documented consumer of the tag
parses it from `<head>` and fetches the `.md` sibling, so tags must
point at the sibling, never the page itself).
- **Drift test**: a vitest file walks `content/md/**` and asserts every
markdown-served slug's page wires the helper (or is covered by the Pages
Router `_app.tsx` mechanism, whose alternate-link wiring the test also
asserts directly so removing it fails CI too). Source-level assertions
by design: page modules can't be imported under www's vitest config.
Fails correctly when wiring is removed (verified by hiding a page and by
altering the `_app.tsx` tag).
- **Vector orphan fixed**: `content/md/vector.md` moved to
`modules/vector` matching the live route (the page previously had no
negotiation or tag, and `/modules/vector.md` 404'd); `/vector.md` now
308s to `/modules/vector.md` and the legacy `/llms/vector.txt` redirect
no longer chains.
- **llms.txt + llms-full.txt**: the `## Product Overview` sections are
gone from both, each keeps a `## Pricing` section. This deletes the
hand-maintained links array (a drift trap) and fixes the accidental
~470-page embed, shrinking llms-full.txt from ~9.8MB to ~4.9MB and
dropping the 4.1MB generated content module from that route's serverless
bundle.

**Note:** this PR is scoped to apps/www only. The docs side
(troubleshooting pages and the rest of the docs surface) is handled
separately through a consolidated manifest-gated mechanism; an earlier
troubleshooting-tag commit was reverted out of this branch to keep the
scopes clean.

<details>
<summary>Why alternate tags matter (background)</summary>

Agents ingest markdown far more efficiently than our rendered HTML: a
fraction of the tokens and no extraction step. Since #47770 removed
UA-based serving (UA sniffing broke a major AI app's fetcher and
poisoned CDN caches), markdown is served only on explicit request: a
`.md` suffix URL, an `Accept: text/markdown` header, or llms.txt. That's
the right serving model, but it makes the markdown twin invisible to any
agent that doesn't already know our URL convention, and the major AI
fetchers send browser/wildcard Accept headers, so bare URLs hand them
HTML.

The `<link rel="alternate" type="text/markdown">` head tag is the
standards-based advertisement of the sibling. It has a documented
consumer today: an agent CLI that parses the tag from `<head>` and then
fetches the `.md` sibling, which is also why the tag must point at a
real sibling URL and never at the page itself. Peer docs sites ship this
tag as table stakes. These www pages used to carry it until the
June/July marketing redesign silently dropped it; the drift test in this
PR turns that regression class into a CI failure.

</details>

## To test

Tested locally (www + docs dev servers):
- [x] `/llms.txt` renders `## Documentation` + single-link `## Pricing`,
no Product Overview
- [x] `/llms-full.txt` renders `# Supabase` → `## Pricing` → `##
Documentation`, no Product Overview, ~4.9MB
- [x] Full www suite: 6 files / 71 tests green; drift test fails
correctly when a page is removed or the `_app.tsx` wiring is altered
- [x] `generateMdContent.mjs` emits `modules/vector`, bare `vector` slug
gone

On the Vercel preview (browser-verified with Playwright):
- [x] Alternate tag present on `/`, `/auth`, `/database`, `/storage`,
`/edge-functions`, `/realtime`, `/pricing`, and a blog post: exactly one
tag each, href = preview origin + `.md` sibling
- [x] `/vector.md` → 308 → `/modules/vector.md`, renders as markdown (`#
Supabase Vector`)
- [x] `/llms.txt` shows single-link `## Pricing`, no Product Overview
- [x] Coverage sweep: all 482 `MD_PAGES` slugs + changelog index/entry
curled on the preview; 471 pages carry exactly one tag, all `.md`
siblings 200 as `text/markdown`. The 11 misses are legacy blog slugs
whose HTML 308-redirects away (stale `MD_PAGES` entries predating this
PR, no head to tag; follow-up tracked in Linear)

Post-merge prod:
- [ ] Full llms.txt link sweep (every linked URL 200s; previews can't
cover the docs-hosted links)

## Linear

- fixes GROWTH-1013


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added Markdown alternate links across key product, pricing, blog, and
troubleshooting pages.
* Added Supabase Vector documentation covering features, use cases,
workflows, and technical details.
* Updated AI-focused documentation indexes with dedicated pricing
content.
  * Added redirects for updated Vector documentation URLs.

* **Tests**
* Added coverage to verify Markdown documentation links stay aligned
with available pages.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-27 17:06:16 +08:00
Danny White 3bca21b3f8 chore(a11y): convert leftover focus recipes to focus-ring (#48219)
## What kind of change does this PR introduce?

Accessibility cleanup (DEPR-628).

## What is the current behavior?

Leftover call sites still use ad-hoc focus recipes
(`ring-foreground-muted`, `outline-brand`, Dialog/Sheet `focus:` rings,
etc.) instead of the shared utilities from #41575.

## What is the new behavior?

Converts those leftovers across `packages/ui`, Studio, www, docs, and
design-system to `focus-ring`, preferring `focus-visible`. Keeps
documented exceptions (`group-focus-visible`, InputGroup `:has()`).

## To test

Tab through controls (keyboard only). Expect a consistent offset ring on
`:focus-visible`, not a green/brand/custom stack, and no ring animation.

### www (marketing)

Preview:
https://zone-www-dot-com-git-danny-depr-628-focus-ring-fbccf9-supabase.vercel.app

- Global nav on `/`: Product, Developers, Solutions dropdowns; logo;
hamburger + mobile menu
- `/features`: view toggles and feature cards
- `/company`: card links
- `/changelog`: timeline / entry links
- `/partners/catalog`: grid/list toggle and partner cards
- `/pricing`: compute section expand control
- Product / Modules / Solutions sticky navs on product pages (e.g.
`/database`, `/storage`)
- `/state-of-startups`: TwoOptionToggle if present

### docs

Preview:
https://docs-git-danny-depr-628-focus-ring-long-tail-supabase.vercel.app

- Any guide page: top nav dropdowns and items
- Narrow viewport: hamburger, then mobile menu links + close
- Guide with PromptPanel / tabs: tab to prompt actions and tab list

### studio (dashboard)

Preview:
https://studio-staging-git-danny-depr-628-focus-ring-long-tail-supabase.vercel.app

- Project home: Connect section tiles; drag-handle focus on sortable
sections
- Integrations marketplace (`/project/<ref>/integrations`): featured
cards, list/grid toggle, list rows
- Auth (`/project/<ref>/auth/oauth-apps`,
`/project/<ref>/auth/providers`): open create/edit sheet, tab to close
(X)
- Database policies (`/project/<ref>/database/policies`): open policy
editor sheet, tab to close
- Storage policies (`/project/<ref>/storage/files/policies`): bucket
section links; policy modal close
- Query performance (`/project/<ref>/observability/query-performance`):
info icon buttons on metrics
- Replication pipeline detail (if available): slot lag / status info
icons
- Support (`/support/new`): attachment add/remove controls
- Table editor: spreadsheet import preview checkboxes; row text/JSON
editor TwoOptionToggle
- Any Dialog/Sheet/toast close (X): ring on keyboard focus only, not
mouse click

### design-system

Preview:
https://design-system-git-danny-depr-628-focus-ring-long-tail-supabase.vercel.app

- Colour palette swatches (keyboard focus)
- Form patterns sidepanel example: avatar / focusable control in the
example

## Additional context

- Linear: [DEPR-628](https://linear.app/supabase/issue/DEPR-628)
- Follow-ups: form-group CSS (DEPR-629), Storage columns selection
(DEPR-630), ESLint rule (DEPR-632)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Accessibility & Usability**
* Standardized keyboard focus indicators across navigation, dialogs,
forms, buttons, toggles, links, and tooltips using a consolidated focus
style.
* Improved toggle controls to use proper button semantics (instead of
clickable text), including `aria-pressed`/disabled handling and better
keyboard navigation.

* **Visual Updates**
* Harmonized hover/focus ring visuals across the design system, Studio,
documentation, and marketing pages while preserving existing layout and
interaction behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-23 08:52:22 +10:00
Danny White 6f6badae51 fix(eslint): promote require-explicit-tabindex to error (#48170)
## What kind of change does this PR introduce?

Accessibility / lint hardening (Safari keyboard focus).

## What is the current behavior?

`supabase/require-explicit-tabindex` is `'warn'`. Studio’s ratchet was
at 0 but the rule was still ratcheted; www / docs / design-system still
had raw `<button>` / `role="button"` call sites without an explicit
`tabIndex`.

[DEPR-627](https://linear.app/supabase/issue/DEPR-627) · follow-up to
#47984 / #48040

## What is the new behavior?

- Shared config: `'supabase/require-explicit-tabindex': 'error'`
- Swept www / docs / design-system (+ Studio test fixtures the ratchet
skipped)
- Removed the rule from the Studio ratchet + baselines

## To test

Prefer **Safari**. This PR only adds explicit `tabIndex` to raw
`<button>` / `role="button"` call sites — not links, and not controls
that already go through `Button` from `ui`.

### Marketing (`www`) ([staging
link](https://zone-www-dot-com-git-danny-depr-627-promote-req-7ae43c-supabase.vercel.app/))

- [x] Homepage frameworks / dashboard feature tabs — Tab through each
tab button
- [x] Product pages (e.g. `/auth`, `/database`) — section tab switchers
- [x] Narrow viewport — open the hamburger; Tab through menu buttons
- [x] `/partners/catalog` — filter / view controls
- [x] Blog view toggle (list ↔ grid)

### Docs ([staging
link](https://docs-git-danny-depr-627-promote-require-explici-25e46d-supabase.vercel.app/))

- [x] **Desktop (≥ lg):** top-right **⋯ menu** (hamburger icon) — opens
a dropdown that includes Theme. Not a separate theme button.
- [x] **Mobile (< lg):** top-right **hamburger** opens the sheet; close
(X) is the raw button we tagged. Theme inside the sheet uses
`ThemeToggle` / `DropdownMenuTrigger` from `ui` (already supposed to set
`tabIndex`).
- [x] **Code blocks** — copy / language controls
- [x] **Is this helpful?** — X / check are `Button` from `ui` (should
already Tab). After voting **while signed in**, the follow-up “What went
well?” / “How can we improve?” text button is the raw one we tagged.
- [x] **AI Tools → Copy as Markdown** (right rail on a guide) — this is
the only GuidesSidebar control this PR changed. “On this page” TOC items
are **links**, not covered by this lint.
- [x] **Reference docs** (e.g. JS client reference) — section headers
that expand/collapse in the left nav (`Collapsible.Trigger`)
- [x] **Troubleshooting index** — type in the search field, then Tab to
the **clear (X)** control

### Dashboard (`studio`)

No production UI changes in this PR (tests + lint config only). Quick
Safari smoke that prior tabindex work still holds:

- [x] Project sidebar — Tab through primary nav links
- [x] Settings → General — Tab through inputs / buttons
- [x] Storage → Files — Tab a bucket row / file actions
2026-07-23 05:21:15 +10:00
claude[bot]andClaude ffd5a93f37 feat(www): add hidden Legal Hub subprocessor list page (draft) (#48100)
<!-- ccr-slack-attribution -->
_Requested by **Nicole Kramer** · [Slack
thread](https://supabase.slack.com/archives/C0161K73J1J/p1783431374242039?thread_ts=1783431374.242039&cid=C0161K73J1J)_

## 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 (`apps/www`).

## What is the current behavior?

No public page for Supabase's subprocessor list, and no way for
customers to be notified when it changes.

## What is the new behavior?

A new hidden page at `/legal/customer-resources/subprocessor-list` shows
the current dated subprocessor PDF and lets anyone subscribe with their
name and email to receive an email whenever the list is updated. The
page is `noindex` and not linked from any nav, so it's shareable by
direct URL only for now. Mirrors Wiz's sub-processor-list page.

**How:**

- **Page**
`apps/www/pages/legal/customer-resources/subprocessor-list.tsx` —
pages-router, mirrors the existing Legal Hub pages (`DefaultLayout`,
`NextSeo`, `PageHeader` + breadcrumb, `SectionContainer` prose). Embeds
the PDF (inline preview + download link) and renders the subscribe form.
Marked `NextSeo` noindex/nofollow and intentionally left unlinked.
- A single `CURRENT_PDF` constant (filename + display date) is the only
thing to change when Legal hands over a new dated PDF.
- **Form** `apps/www/components/SubprocessorUpdatesForm.tsx` — mirrors
`SecurityNewsletterForm` (First name, Last name, Email; `ui`
primitives). Carries the framing copy verbatim, with **Subscribe to
updates** bold and Privacy Policy linked to
https://supabase.com/privacy.
- **API route**
`apps/www/app/api-v2/submit-form-subprocessor-updates/route.tsx` — exact
mirror of `submit-form-security-newsletter`; subscribes the user to the
Customer.io "Subprocessor Alerts" subscription (topic 4) via
`cio_subscription_preferences.topics.topic_4: true`.
- **PDF** `apps/www/public/legal/subprocessor-list/June-1-2026.pdf`.

**Updating the list in future:** Drop the new dated PDF into
`apps/www/public/legal/subprocessor-list/` and update the `CURRENT_PDF`
constant. Nothing else changes.

## Additional context

**Notes / to confirm:**

- Customer.io topic id `4` → `topic_4` (per Prashant); not independently
verified against Customer.io.
- Draft: page is intentionally unlinked and noindex until Legal signs
off.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01D9WS2QWQ8Y3o7PqDZabS3F)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-22 11:19:14 +01:00
Saxon Fletcher 74a0848ea5 Update logos on homepage (#48087)
Updates logos on homepage and removes slider
2026-07-20 15:02:53 +10:00
Francesco Sansalvadore 13330e6328 fix(ui): expandable video preview image (#47964)
## What kind of change does this PR introduce?

Restore preview image on ExpandableVideo trigger component.

## What is the current behavior?
<img width="1441" height="698" alt="Screenshot 2026-07-15 at 14 08 58"
src="https://github.com/user-attachments/assets/bdb1c4be-71a9-4601-b5c9-ab4fc97c48d1"
/>

<img width="1273" height="701" alt="Screenshot 2026-07-15 at 14 09 05"
src="https://github.com/user-attachments/assets/b8026bcc-3d43-4faa-873b-1745b32c166c"
/>

## What is the new behavior?
<img width="1434" height="678" alt="Screenshot 2026-07-15 at 14 08 53"
src="https://github.com/user-attachments/assets/8a3e64d1-5fe7-4ab9-a71b-3de5808d28b9"
/>

<img width="1160" height="672" alt="Screenshot 2026-07-15 at 14 08 48"
src="https://github.com/user-attachments/assets/db598a47-ed8e-435b-b3ef-8ae9e76761a2"
/>

---

Also fixed a border-b issue on the PartnerCatalogDetail.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
  - Added thumbnail previews for partner catalog YouTube videos.
- Improved video preview presentation with clearer overlays and stronger
image blur.

- **Bug Fixes**
  - Updated image loading support for YouTube thumbnail URLs.
  - Refined sticky tab header spacing and alignment while scrolling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 14:53:32 +02:00
d23f86021a feat(www): Partner Catalog update (#46757)
## Info architecture change around "Partners"

The www "integrations" now become more partner-driven.
`/partners/integrations` -> now Partner Catalog under
`/partners/catalog` (old links redirect to new paths)

Moved them close together in the nav dropdown and in the footer
<img width="494" height="336" alt="Screenshot 2026-07-09 at 11 06 41"
src="https://github.com/user-attachments/assets/a875fef0-0ab8-47ca-8756-d658b27c4892"
/>
<img width="1149" height="665" alt="Screenshot 2026-07-09 at 11 09 48"
src="https://github.com/user-attachments/assets/9631bb72-fe25-4fb4-b1af-9f14a37d02e7"
/>

## /partners 

This page remains untouched in this PR, updates to layout, content and
intake form are delegated to #47874

## /partners/catalog

Listed in the
[catalog](https://zone-www-dot-com-git-feat-www-partners-pages-supabase.vercel.app/partners/catalog)
are now partners. Some partners match with a listing.

<img width="1207" height="866" alt="Screenshot 2026-07-09 at 11 14 17"
src="https://github.com/user-attachments/assets/b65216be-976f-4ef5-91f8-1ad49da87b45"
/>

## /partners/catalog/[partner]

Each partner can have one or more "listings" which are either 
- simple guides
- foreign data wrappers
- dashboard integrations

Integrations available in the dashboard now all have a prominent
"Install integration" cta to open it in the dashboard [integrations
page](https://supabase.com/dashboard/project/_/integrations).

<img width="1269" height="776" alt="Screenshot 2026-07-09 at 11 16 51"
src="https://github.com/user-attachments/assets/3c7bb715-ffce-4d0a-905f-9a660c3b1f5a"
/>

## Docs

Update docs →
[Preview](https://docs-git-feat-www-partners-pages-supabase.vercel.app/docs/guides/integrations)
- remove "Supabase marketplace"
- use "Dashboard Integrations and Partner Catalog
- update integrations in sidenav to link to updated /partners/catalog/**
listings

<img width="1520" height="696" alt="Screenshot 2026-07-15 at 12 54 47"
src="https://github.com/user-attachments/assets/9f5a2794-4536-4299-97df-9732d3d75b4c"
/>

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a Partner Catalog experience with search, category filters,
official-partner toggle, responsive filtering (sidebar + bottom sheet),
grid/list views, and featured partners.
* Added Partner Catalog detail pages with tabbed listings, MDX-rendered
content, image gallery with zoom overlay, and “add/install” actions.
* **Improvements**
* Updated “Become a Partner” layout and form support for prefilled
values and checkbox-group fields (including validation).
* Updated navigation/footer/docs and partner tile links to use Partner
Catalog routes; expanded redirects from legacy integrations paths.
  * Added public agent-skills discovery manifest.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alan Daniel <stylesshjs@gmail.com>
Co-authored-by: Alex Hall <alex.hall@supabase.io>
Co-authored-by: Miranda Limonczenko <miranda.limonczenko@supabase.io>
2026-07-15 11:10:51 +00:00
Pamela Chia 1b1b1ea0e0 chore: remove dead telemetry code (#47950)
## Summary
Removes two pieces of dead telemetry code found while root-causing the
docs pageview re-fire investigation (GROWTH-997, closed with no fix
needed). Pure deletion, 30 lines, no behavior change.

## Changes
- Delete `apps/www/app/ConsentWrapper.tsx`: an unwired third
`PageTelemetry` mount. www already mounts `PageTelemetry` in
`pages/_app.tsx` (Pages Router) and `app/providers.tsx` (App Router);
nothing imports this wrapper.
- Remove the exported `POSTHOG_URL` constant from
`apps/studio/lib/constants/index.ts`: zero consumers. The CSP allowlist
in `apps/studio/csp.ts` defines and uses its own local `POSTHOG_URL`,
which stays.

## Testing
Deadness verified before deletion, on current master:
- [x] Repo-wide grep for `ConsentWrapper`: only self-references inside
the deleted file
- [x] Repo-wide grep for `POSTHOG_URL`: remaining references are the
`csp.ts` local const only

## Linear
- fixes GROWTH-1002


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Removed an obsolete consent-related page wrapper to streamline page
behavior.
* Updated application configuration handling without changing existing
payment or usage settings.

* **Refactor**
* Simplified internal configuration and page composition while
preserving the existing user experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-15 12:01:29 +01:00
Francesco Sansalvadore 20cb05230b fix site_title (#47884)
Update www `site_title`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated the site title and browser metadata to describe the product as
“The Postgres Development Platform.”

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 13:41:26 +00:00
Katerina Skroumpelou 373e917a99 feat(docs): generate server.txt reference and wire into www llms (#47782)
Add a `server` entry to the reference-markdown pipeline so it emits
`public/markdown/reference/server.md`, and register the Supabase Server
Library Reference as a source in the www `llms.txt` and `llms-full.txt`
routes.




<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Added a new Supabase Server Library Reference covering server-side SDK
usage.
* Included the server reference in generated documentation and plaintext
documentation indexes.
* Made server SDK reference content available through the full
documentation feed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-10 11:56:20 +01:00
Francesco Sansalvadore 532ac3638d fix(www): update customer logos from svg to pngs (#47777)
Some customer pages didn't show og-images properly because satori breaks
using svgs.

This PR replaces all customer logos from svgs to pngs. 
They're all exported at least 2x to 4x so image quality shouldn't get
worse anywhere.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Updated several customer story pages and related listings to use PNG
logo assets, improving logo rendering consistency across the site.
* Refreshed the customer RSS feed metadata and removed a duplicate entry
so the feed stays up to date and cleaner.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-09 15:33:28 +02:00
Saxon FletcherandClaude Opus 4.8 fb02182e86 Color system (#47288)
## 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.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Refreshed theming across the UI to use modern color expressions and
shared theme variables (including OKLCH-based gradients), improving
consistency for charts, code blocks, overlays, icons, and decorative
backgrounds.
* **Bug Fixes**
* Improved light/dark color and gradient consistency across axis/grid
styling, reference lines, buttons/badges, sidebar accents, loaders, and
other visual components.
* **Documentation**
* Updated styling/theming guidance to align with the revised semantic
token system and the updated theme variable usage patterns.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:00:43 +10:00
Francesco Sansalvadore aa764e4013 chore(www): refine www styling (#47499)
### Logo positioning bug on Safari

#### Before
<img width="1538" height="1404" alt="CleanShot 2026-07-01 at 07 11
55@2x_b0d735b7df6470afb861f4e82cfeed554743cec621475197e07ff39a98c5c506"
src="https://github.com/user-attachments/assets/dc8483bd-5a2a-4d89-9b90-d0ab3529b4b5"
/>


#### After
<img width="1177" height="526" alt="Screenshot 2026-07-01 at 15 25 59"
src="https://github.com/user-attachments/assets/e5ab66eb-56eb-4f1b-8a66-783aafad069d"
/>

### Uniform h1 styling

#### Before
Font-weight too heavy
<img width="721" height="504" alt="Screenshot 2026-07-01 at 15 55 53"
src="https://github.com/user-attachments/assets/4dc4e157-f746-4626-9ec7-5e893d7155ba"
/>

#### After
<img width="693" height="410" alt="Screenshot 2026-07-01 at 15 56 04"
src="https://github.com/user-attachments/assets/c012d6e5-0889-4466-b2b2-56d1c9516e27"
/>

### AI Builders platform card
### Before
<img width="675" height="573" alt="Screenshot 2026-07-01 at 16 18 31"
src="https://github.com/user-attachments/assets/a34e2fde-115b-45e8-8d44-9fc32c22c0a1"
/>

### After
<img width="640" height="576" alt="Screenshot 2026-07-01 at 16 18 23"
src="https://github.com/user-attachments/assets/45ebf1c7-6508-40de-a755-dda17824979a"
/>

### Logo theme-awareness on 404 page

#### Before
<img width="1053" height="670" alt="Screenshot 2026-07-02 at 11 22 45"
src="https://github.com/user-attachments/assets/d1f45cc8-00ad-48ad-a21a-3b92bf6097f0"
/>

#### After
<img width="1053" height="666" alt="Screenshot 2026-07-02 at 11 22 28"
src="https://github.com/user-attachments/assets/8b6435aa-da87-46f3-9d5c-750f8222edb1"
/>

---

Plus other minor padding/spacing issues:
- remove customer stories in homepage
- use correct container width and align "Use Supabase with [framework]"
section
- restore default `--font-sm` sizing as it resulted too small for www

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes / UI Improvements**
* Refined spacing, layout, and responsive styling across multiple
homepage sections.
* Improved featured logo positioning and adjusted community/hero copy
sizing.
  * Updated site typography for better readability and wrapping.
* Refreshed the 404 experience with a smoother reveal animation and
consistent layout.
  * Updated deep dark-mode behavior to apply only during launch weeks.
* **Performance**
* Lazy-loaded multiple homepage sections to improve initial load and
perceived speed.
* **SEO / New Features**
  * Added a dedicated 404 page that disables indexing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-03 03:14:43 +10:00
Francesco Sansalvadore a54a2b69e1 www: homepage (#47228)
- Update homepage based on new designs from #43455.
- Also improve a11y and semantics of homepage as per @czenko's
[review](https://github.com/supabase/supabase/pull/43455#pullrequestreview-4548881985)

PR breakdown of #43455 
Related: #47226 #47227 #47236
2026-07-01 12:13:15 +00:00
Francesco Sansalvadore acbb19a69a feat: www & docs fonts (#47227)
Update marketing website and docs with new sans-serif fonts:
- `Inter` - sans-serif for all body text
- `Manrope` - sans-serif for headings

PR breakdown of #43455 
Related: #47226 #47228 #47236
2026-07-01 12:59:00 +02:00
Francesco Sansalvadore ba133afc4c www: blog (#47236)
Update blog layout.

PR breakdown of #43455 
Related: #47226 #47227 #47228
2026-06-30 10:28:17 +02:00
Prashant Sridharan ff1941b35f Revise State of Startups landing page (#47335) 2026-06-30 01:35:40 +01:00
Francesco Sansalvadore cd62b0b9d4 www: product pages (#47271)
Update product pages in marketing website.

PR breakdown of #43455 
Related: #47226 #47227 #47228 #47236
2026-06-26 15:47:52 +02:00
Francesco Sansalvadore 90ef7ea874 www: standardize container width (#47226)
Define and clean up standard container width definition for marketing
website.

PR breakdown of #43455 
Related: #47227 #47228 #47236
2026-06-24 10:26:38 +00:00
Prashant Sridharan 4dd3a0aacf Fix events page (#47089)
## 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 context, the events page pulls data from our webinar MDX files, Luma
(for Hackathons, Events, and Meetups), and Notion (for third-party
events we participate in). I recently unified our multiple Luma
calendars into one and started using tags for Luma events.

I fixed a few things on the /events page:

1. Webinars now show the proper location instead of "Unknown"
2. Event cards now show location properly depending on where the source
of the events are
3. Event data is pulled from Luma and categorized based on tags.
Fallback tag is "event" if a tag is absent

Note that this structure assume that Notion events are third-party, Luma
events are first-party (Hosted by Supabase), and Webinars are always
online. This is a safe assumption for the time being, but I will revisit
in the future if that changes.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Events now display tags and categories from Luma event data.
* Webinar events are identified and labeled as "Supabase Live" with a
video icon for improved visibility.

* **Improvements**
* Enhanced event metadata display with improved location and category
information.
* Streamlined event categorization for more consistent handling across
event sources.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-18 18:58:27 +01:00
Gildas GarciaandIvan Vasilov 96d43099bb chore: refactor Button API so that it can be used a standard button (#46880)
## Problem

Our `<Button>` component breaks the default `button` contract by
redefining the `type` prop to set its variant (`primary`, `default`,
etc) instead of the button type (`submit`, `button`, etc).
This is confusing and forces to write more code when using it with
shadcn components that expect/inject the standard button props.

## Solution

- rename the `type` prop to `variant`
- rename the `htmlType` prop to `type`
- propagate the changes where necessary
- format code

## How to test

As this is just prop renaming, if it builds it's ok

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-16 23:59:58 +02:00
Jeremias Menichelli 575ac8c645 [DOCS-979] feat(Docs): Generate new markdown files for reference pages (#46727)
In this PR:
- The `llms.ts` script is removed from the pipeline. It was just
iterating over the sections of the SDK JSON files to generate _dummy_
text files for LLMS to consume. But with a lot of inconsistencies and
mistakes.
- There's a new script that builds markdown files from the SDK
definition files.
- The Management API now has a definition file too, it was missing
before.
- On the www project now there are redirects for the reference text
files to the new markdown files in the docs project.
- NPM scripts have received better names so that prebuild ones are
smaller and all are easier to differentiate.
2026-06-09 10:39:55 +02:00
Jeremias Menichelli 5288f8bd5f [DOCS-951] [DOCS-952] Update llms and llms-full text files to match industry standards (#46166) 2026-05-27 16:58:19 +02:00
Alan Daniel 87408ed9d9 chore(www): add State of Startups 2026 OG image (#46394)
## 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?

Chore — adds a static asset.

## What is the current behavior?

The State of Startups 2026 page references
`/images/state-of-startups/2026/state-of-startups-og.png` for its Open
Graph image, but the file did not exist in the repo.

## What is the new behavior?

Adds the OG image at the expected path so social previews render
correctly when sharing `/state-of-startups`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Style**
* Adjusted the minimum height of the State of Startups header and its
inner wrapper on non-medium breakpoints to refine spacing and visual
balance.
* Medium-breakpoint height remains unchanged, preserving the intended
layout at that size.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46394?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 21:47:37 +00:00
Alan Daniel 2f50a0fb91 feat(www): add missing pull quotes and participants carousel to State of Startups 2026 (#46401)
## 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

## What is the current behavior?

The 2026 State of Startups page is missing several selected pull quotes,
the Outlook chapter ends on a single static quote, and the "Thank you"
footer still renders the 2025 participants list as a static wrap of ~60
companies.

## What is the new behavior?

- Wires the six selected pull quotes for chapters 1–4 and 7 (with
section-level support so the Solo Founders quote sits inside its
section). `SurveyPullQuote` now accepts optional author position and
avatar.
- Replaces the Outlook chapter quote with a new
`SurveyPullQuoteCarousel` that rotates between four labelled quotes
(Burn out, Pace of change, Competition, Runway) and reuses the existing
stipple/checker timer-bar pattern.
- Replaces the participants list with all 326 verified 2026 entries and
renders them via a new `ParticipantsCarousel` — five horizontal marquee
rows scrolling at different speeds and alternating directions, pausing
on hover, with edge fades and `prefers-reduced-motion` support.

## Additional context

Participants list sourced from the verified
`state-of-startups-2026-companies-software-verified.csv` export.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Rotating quote carousels for survey chapters with progress indicators
and subtle animations
  * Animated participants display as multi-row scrolling marquees
  * Optional author position and avatar shown with quotes
  * Reduced-motion support to disable animations

* **Updates**
* Refreshed State of Startups 2026 content and expanded participants
list

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46401?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 16:22:57 -04:00
Alan Daniel adeb6bf56c fix(www): bucket Codex/ChatGPT/OpenAI responses in SoS chart (DEBR-302) (#46398) 2026-05-26 20:39:50 +01:00
Alan Daniel 56c34d20f8 feat(www): wire up State of Startups 2026 results page (#45231)
## 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 — ports real 2026 survey data and narrative into the existing
`apps/www/app/state-of-startups` page.

## What is the current behavior?

The 2026 page renders the pre-launch `<RegisterContent />` signup form
(`SHOW_RESULTS = false`), and the 2026 chart components still query
`responses_2025` via the unsuffixed 2025 RPCs. The chapter narrative in
`state-of-startups-2026.tsx` is placeholder copy cloned from 2025, and
there are no charts for any of the new-in-2026 survey questions (auth
provider, share of AI-generated code, paid AI/product subscriptions,
agent building, MCP adoption).

## What is the new behavior?

- Flips `SHOW_RESULTS` to `true` so `/state-of-startups` renders
`<StateOfStartups2026Content />`.
- Repoints the 14 carry-over chart components to `responses_2026` and
calls `_2026`-suffixed RPC siblings (the original 2025 RPCs stay intact
so the 2025 page can live at its own URL).
- Adds 5 new chart components — `AuthProviderChart`,
`AICodebasePercentChart`, `PaidSubscriptionsChart`,
`BuildingAgentsChart`, `MCPAdoptionChart` — and wires them into
`SurveyChapterSection`'s chart registry.
- Rewrites `state-of-startups-2026.tsx` into 8 chapters with real 2026
narrative, pull quotes, and summarized answers from the source-of-truth
`supabase/state-of-startups` repo.
- Adds `.context/**` to `.prettierignore` so the scratch directory
holding the companion SQL migrations is ignored.

## Additional context

Backend changes live in the separate `supabase/state-of-startups` repo /
project `iddgenoqmqztnnefcbwp`: a `responses_2026` table, 5 new
2026-only RPCs, and 14 `_2026`-suffixed siblings of the existing RPCs
(drafts staged under `.context/sos-2026-survey-sql/` locally, not in
this PR). This PR's chart fetches will error until those migrations are
applied and `2026-responses.arrayified.csv` is loaded.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Released State of Startups 2026 results with a year selector,
preloaded results cache for faster viewing, and hourly revalidation.
* Added new interactive charts (AI codebase share, auth providers,
biggest challenges, building agents, MCP adoption, paid subscriptions,
location) and updated many charts for 2026; charts now show “added in
2026” when not available.

* **UX**
* Reworked page layout: floating table of contents relocated, year
toggle added, and animations simplified for smoother transitions.

* **Documentation**
* Restructured survey narrative into new thematic chapters, revised
chapter content, stats, and visuals.

* **Chores**
  * Updated formatting ignore rules to skip generated/context files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 15:17:00 +01:00
Prashant SridharanandAlan Daniel 8cd39680ef Added on-demand webinars as an option in the event list (#46215)
## 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 a pill for on-demand webinars in the /events page. Previously,
webinars were not shown if they had passed. But we embed the video for
the webinar into the landing page so people can discover and find it.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an "On-demand" event category with dedicated filtering and a
separate on-demand view
* Events page now loads on-demand content and shows "On-demand" badges
where appropriate

* **UI/UX Improvements**
* Banner hides when viewing on-demand events; subtitle updates per view
* Event card layout and badge placement refined; sorting and empty-state
messaging adapt to selected category

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46215?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alan Daniel <stylesshjs@gmail.com>
2026-05-21 16:20:17 +01:00
Gildas Garcia 86a3f8b03d chore: upgrade to react-19 (#45886)
- Most changes are related to either types or `useRef` usages (it now
requires an initial value).
- also updated `vaul` to its latest version and haven't noticed any
change ([design-system
demo](https://design-system-git-react-19-supabase.vercel.app/design-system/docs/components/drawer))

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Upgraded workspace to React 19.

* **Bug Fixes**
* Improved null-safety and ref handling across editors, UI components,
shortcuts, and markdown/image rendering to reduce runtime errors.
* Safer event/timeout/interval cleanup and more robust command/context
handling.

* **Chores**
  * Bumped vaul dependency versions.

* **Documentation**
* Type and TypeScript accuracy improvements for clearer developer
feedback.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 16:04:41 +02:00
Alan Daniel 73286972fb feat(www): load _events mdx files on /events listing (#45176)
## 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

## What is the current behavior?

The /events page only loads events from the Notion "Developer Events"
database and the Luma Community API. MDX files under `apps/www/_events/`
(including webinars like agency-webinar, sentry, datadog, figma-make)
are not surfaced on the listing, and past events could still appear
until the moment they ended because the filter compared against `now()`
rather than the current day.

Addresses
[DEBR-85](https://linear.app/supabase/issue/DEBR-85/events-page-powered-by-notion-page).

## What is the new behavior?

- New `getMdxEvents()` reads `apps/www/_events/*.mdx`, parses
frontmatter with `gray-matter`, and returns today-and-future events as
`SupabaseEvent`s.
- `/events` now merges Notion + mdx + Luma events.
- Past events are hidden across all sources by comparing against the
start of today (UTC) instead of `now()`, so events running today stay
visible throughout the day.

## Additional context

Links on mdx events point at the main_cta URL when it's an external
\`http(s)\` URL, otherwise fall back to the built \`/events/{slug}\`
page so on-demand recordings remain reachable.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Events can be sourced from MDX files and merged into site event
listings.
* Luma supports multiple calendars (community and hackathon) for richer
feeds.

* **Improvements**
  * Events now exclude anything before the start of the current UTC day.
  * Added a “Community Event” category filter and included it in counts.
  * Event title typography adjusted for improved readability.
* “Hosted by” text now only shows when hosts exist; host fallbacks
standardized.

* **Chores**
  * Build env updated to include hackathon API key.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-08 11:22:35 -04:00
Ivan VasilovandClaude Sonnet 4.6 afd690ada5 chore: Migrate all apps to use Tailwind CSS configs (#45530)
This PR migrates all tailwind configs in the apps to be CSS configs.
They import a shared CSS Tailwind config from the `config` package
(which in turns imports the old JS config).

The shared JS config will be migrated to CSS in a followup PR.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Centralized Tailwind into a config-driven entrypoint and updated the
app build flow to use the new build step; many apps now import unified
global styles.

* **Style**
* Migrated global styles to a Tailwind v4-style setup, added
project-wide content scanning, consolidated theme imports, standardized
theme tokens (including new --container-site max-width), and added a
small prose utility to remove paragraph margins.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 17:18:15 +02:00
Pamela Chia c26b64a033 feat(www): emit BreadcrumbList JSON-LD on marketing surfaces (#45478)
## Summary

- Adds `breadcrumbListSchema(items)` helper to `apps/www/lib/json-ld.ts`
and a hand-curated `apps/www/lib/breadcrumbs.ts` route map.
- Wires inline `<script type="application/ld+json">` BreadcrumbList
blocks into 18 marketing surfaces: blog (index + slug), customers (index
+ slug), events (index + slug), 5 product pages (database, auth,
storage, edge-functions, realtime), 3 modules (vector, cron, queues),
pricing, careers, company, features.
- Pages router callers wrap the script in `<Head>`; app router callers
place it directly in JSX. Dynamic surfaces append a leaf at render time
using the page's title (`frontmatter.title` for blog, `meta_title ??
title` for customers, `event.meta_title ?? event.title` for events).
- Modules sit at `Home > {Name}` since no `/modules` index page exists;
products sit at `Home > {Product}` (no shared products parent). Absolute
`https://supabase.com` URLs match the existing `CANONICAL_ORIGIN`
convention so anchors stay stable across Vercel previews.

Linear:
[GROWTH-822](https://linear.app/supabase/issue/GROWTH-822/add-breadcrumblist-json-ld-to-www-marketing-surfaces)
(sub-issue under
[GROWTH-724](https://linear.app/supabase/issue/GROWTH-724)).

> **Note on branch name:** the branch is
`pamela/growth-820-www-breadcrumb-jsonld`; the actual Linear issue is
GROWTH-822. The branch was named before the sub-issue was created.
Ignore the `820` in the branch.

Explicitly deferred (separate PRs / low SEO ROI): `/launch-week/*`,
`/solutions/*`, `/partners/*`, `/alternatives/*`, `/changelog`,
`/legal/dpa`, `/aws-reinvent-2025`, `/wrapped`, `/contribute/*`,
`/brand-assets`, `/ga`, `/ga-week`, `/state-of-startups*`, and the
homepage (Organization + WebSite already cover homepage entity signals;
single-item BreadcrumbList is ignored by Google).

## Test plan

- [x] On the Vercel preview, `curl -s https://<preview>/database | grep
'"BreadcrumbList"'` returns the script block with `Home > Database`.
- [x] `curl -s https://<preview>/blog/<recent-slug> | grep
'"BreadcrumbList"'` returns `Home > Blog > {post title}`.
- [x] `curl -s https://<preview>/customers/<slug> | grep
'"BreadcrumbList"'` returns `Home > Customer Stories > {customer
title}`.
- [x] `curl -s https://<preview>/events/<slug> | grep
'"BreadcrumbList"'` returns `Home > Events > {event title}`.
- [x] `curl -s https://<preview>/modules/vector | grep
'"BreadcrumbList"'` returns `Home > Vector`.
2026-05-05 23:57:53 +08:00
Ivan Vasilov 97a8df0a23 feat: Handle the classic-dark theme in www and docs apps (#45214)
This PR fixes a bug where a user might choose `classic-dark` as a theme
in `studio` but then `docs` and `marketing` apps will look weird.

To test:
- Change the localStorage value of `theme` to `classic-dark`
- Open `www` and `docs` apps, they should look ok

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a new "classic-dark" theme option for enhanced visual
customization.

* **Improvements**
* Unified and simplified theme handling across apps for more consistent
behavior.
* Improved system-theme detection and smoother transitions when
switching themes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-05 16:18:46 +02:00