feat(invites): add dedicated /invite route - #328
Conversation
Replaces the split invite handling in __root.tsx (inline overlay for anonymous users, silent toast for authed ones) with one dedicated /invite screen both states pass through. Root beforeLoad now redirects any request carrying ?invite= to /invite, capturing where the user was actually headed (redirect) so they land back there after accepting — same host, since it's all client-side SPA navigation. Authed accept failures now get a real error screen with retry instead of a toast. Also retires the two single-item auto-redirect guards added for the subdomain invite bug, since the root-level redirect to /invite now intercepts before they'd ever see a pending invite.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Playwright test resultsDetails
|
There was a problem hiding this comment.
Pull request overview
Adds a dedicated /invite route and centralizes invite-link handling so both anonymous and authenticated users pass through the same screen, with the root route redirecting any ?invite= traffic to /invite and then returning users to their original destination after acceptance.
Changes:
- Introduces a new
/inviteroute that validates an invite token, renders the invite landing UI, and auto-accepts for authenticated users with a retryable error state. - Updates the root route to redirect any URL containing
?invite=to/invite, and removes the previous inline invite overlay/toast flow. - Removes prior “single festival/edition auto-redirect” invite guards and adjusts URL-state clearing behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/routeTree.gen.ts | Registers the new /invite route in the generated TanStack Router tree. |
| src/routes/invite.tsx | New dedicated invite screen/flow (validate, accept, error/retry, redirect). |
| src/routes/index.tsx | Removes search.invite special-casing from the single-festival auto-redirect guard. |
| src/routes/festivals/$festivalSlug/index.tsx | Removes search.invite special-casing from the single-edition auto-redirect guard. |
| src/routes/__root.tsx | Redirects any ?invite= URL to /invite and removes the old root-level invite handling UI/logic. |
| src/hooks/useUrlState.ts | Changes clearFilters to clear all search params (previously preserved invite). |
| src/components/invite/useInviteFlow.ts | Deletes the old invite-flow hook (logic moved into /invite). |
| src/components/invite/useInviteFlow.test.tsx | Deletes unit tests for the old invite-flow hook. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Keep the mutation as a single object instead of destructuring, use the ReactNode type import, and extract the joining/error state into its own JoiningState component.
Root's invite redirect now carries the destination's remaining search params and hash, not just the pathname, so filter/sort state on the original URL survives the round trip through /invite. Bare /invite (no ?invite=) previously threw an uncaught search validation error. Add an errorComponent that redirects to / instead.
Replaces the split invite handling in
__root.tsx(inline overlay for anonymous users, silent toast for authed ones) with one dedicated/invitescreen both states pass through. Root now redirects any request carrying?invite=to/invite, remembering where the user was actually headed so they land back there after accepting — same host, since it's all client-side navigation. Authed accept failures now get a real error screen with retry instead of a toast. Also retires the two single-item auto-redirect guards from the earlier fix, since the root-level redirect now intercepts before they'd ever see a pending invite.Verification
/inviteand shows the "you're invited" screen, unaffected by which route the link originally pointed to./invite?invite=TOKENdirectly with noredirectparam; lands on/after accepting.Generated by Claude Code