Files
supabase/apps/studio/pages/join.tsx
Danny White 791fc74412 feat(studio): shared connect layout for organisation invites (#45774)
## What kind of change does this PR introduce?

Feature. Part of DEPR-279.

## What is the current behavior?

The organization invite page has its own bespoke centered card and
page-level Supabase logo.

## What is the new behavior?

Introduces a minimal shared interstitial layout and migrates `/join`
onto it as the first small connect-surface slice. The invite API and
accept-invite mutation paths are unchanged.

| Before | After |
| --- | --- |
| <img width="1024" height="794"
alt="Supabase-F2325C57-D5DE-445D-8083-12EF8A1EE0CA"
src="https://github.com/user-attachments/assets/b23dcc7a-c649-4b59-9393-9232d74f0c6b"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-66CDA329-0531-4B12-AC32-A7E21931F876"
src="https://github.com/user-attachments/assets/454917ce-1a96-4e50-b003-6c16a541b39a"
/> |
| <img width="1060" height="822" alt="CleanShot 2026-03-13 at 11 04
43@2x-2616AECB-8203-4439-A1CD-45AB18FC4CA8
1-584A0600-CCE0-4F16-9111-9BEB94BE85EC"
src="https://github.com/user-attachments/assets/871c7dcb-120e-40cd-afc8-2cec95e4b7ae"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-26AD978E-4CF9-4600-9885-082084349E94"
src="https://github.com/user-attachments/assets/ee9bfaff-dde4-4366-abae-77dc8a95c4ef"
/> |
| <img width="1024" height="794"
alt="Supabase-4993D74C-D62B-43B7-9681-826BE1591AC4"
src="https://github.com/user-attachments/assets/1c411ae0-90e7-481d-a4cc-3eac26267291"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-C84D4E4C-24F5-463D-B1D6-D11D3256596F"
src="https://github.com/user-attachments/assets/688387a4-3c49-41db-b89c-7c5531e91aed"
/> |
| <img width="1024" height="794"
alt="Supabase-D9BD2601-98A4-489D-A51D-CEB73F51FA6F"
src="https://github.com/user-attachments/assets/6d1da65f-d655-4047-9f6a-db65f8c0a729"
/> | <img width="1024" height="794" alt="Join Organization
Supabase-50065F40-179A-4BD6-8F1D-6106FFD8A15C"
src="https://github.com/user-attachments/assets/e61809f9-dcec-4e51-ba94-91b04010ec50"
/> |

## Testing notes

Staging invite emails are generated with the fixed staging dashboard
origin, for example:

```text
https://supabase.green/dashboard/join?token=...&slug=...
```

To test this PR preview with a real invite token, keep the path and
query string from the email but replace the origin with the Vercel
preview origin, for example:

```text
https://studio-staging-git-dnywh-featconnect-interstitial-join-supabase.vercel.app/dashboard/join?token=...&slug=...
```

### Manual state checks

- **Signed out:** open the swapped invite URL in an incognito window or
a browser signed out of Studio. Expected: `View invitation`,
sign-in/create-account actions, and no loading skeleton hang.
- **Wrong account:** sign in to the PR preview as an account that is not
the invite recipient, then open the swapped invite URL. Expected: `Wrong
account`, warning callout, and `Sign out`.
- **Happy path:** sign in as the invited email address, then open the
swapped invite URL. Expected: `Join {Organization}`, signed-in account
row, `Accept invite`, and `Decline`. Accepting should join the
organization.
- **Invalid token:** alter one character in the token in the swapped
invite URL. Expected: invalid invite state.
- **No longer valid:** accept the invite once, then open the same
swapped invite URL again. Expected: no-longer-valid/already-used state,
depending on the backend response.

### Test-covered states

Expired invites, generic backend error, loading, and
create-account-disabled states are harder to force manually in staging.
They are covered by `tests/components/OrganizationInvite.test.tsx`.

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

* **Refactor**
* Redesigned the organization invitation experience with an interstitial
layout, clearer early-return flows for signed-out, loading,
expired/invalid, wrong-account, and accepted-invite states; primary CTA
now reads “Accept invite”.
* Streamlined error and sign-out flows with clearer, focused messaging.

* **New Features**
* Added a reusable interstitial layout and compact account row for
invitation screens.

* **Tests**
* Added comprehensive tests covering invite states, accept/decline
actions, and error handling.

[![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/45774)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-12 10:41:47 +10:00

21 lines
548 B
TypeScript

import Head from 'next/head'
import { OrganizationInvite } from '@/components/interfaces/OrganizationInvite/OrganizationInvite'
import { buildStudioPageTitle } from '@/lib/page-title'
import type { NextPageWithLayout } from '@/types'
const PAGE_TITLE = buildStudioPageTitle({ section: 'Join Organization', brand: 'Supabase' })
const JoinOrganizationPage: NextPageWithLayout = () => {
return (
<>
<Head>
<title>{PAGE_TITLE}</title>
</Head>
<OrganizationInvite />
</>
)
}
export default JoinOrganizationPage