This release includes 1 breaking change for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+8 more
Affected surfaces
ReleasePort's take
Light signalThe sign‑in experience now respects the user's locale, remembers pre‑login destinations, and lands users in an accessible environment after authentication.
Why it matters: These UX improvements—locale awareness (fact 7889), deep‑link preservation (fact 7890), and correct post‑login routing (facts 7891/20064)—directly enhance user satisfaction for developers, SREs, and security engineers managing auth flows.
Summary
AI summarySign-in flow now respects locale, remembers deep‑link destinations after login, and lands users in an environment they have access to.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Feature | Medium |
Auth pages now respect the user's locale. Auth pages now respect the user's locale. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Sign-in remembers the original page before being bounced. Sign-in remembers the original page before being bounced. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
App lands on an environment the user actually has access to after sign-in. App lands on an environment the user actually has access to after sign-in. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: low |
— |
| Feature | Medium |
404 errors now render inside the admin shell with sidebar visible. 404 errors now render inside the admin shell with sidebar visible. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: low |
— |
| Feature | Medium |
Sign-in / sign-up / 2FA / password-reset cards have a new subtle grid-and-glow background based on brand HSL variable. Sign-in / sign-up / 2FA / password-reset cards have a new subtle grid-and-glow background based on brand HSL variable. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: low |
— |
| Feature | Medium |
Post‑sign‑in landing selects an environment the user actually has access to, using context, localStorage, primary env, or first available env. Post‑sign‑in landing selects an environment the user actually has access to, using context, localStorage, primary env, or first available env. Source: granite4.1:30b@2026-05-21-audit Confidence: low |
— |
| Feature | Low |
Unknown URLs while not logged in funnel through sign‑in flow, preserving ?next=; redirects to /auth/setup-admin on incomplete self‑host instances. Unknown URLs while not logged in funnel through sign‑in flow, preserving ?next=; redirects to /auth/setup-admin on incomplete self‑host instances. Source: granite4.1:30b@2026-05-21-audit Confidence: low |
— |
| Dependency | Medium |
`packages/hooks/src/hooks/gql.ts` split into `hooks/auth.ts` module for auth domain hooks. `packages/hooks/src/hooks/gql.ts` split into `hooks/auth.ts` module for auth domain hooks. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Bugfix | Medium |
OAuth failure now redirects to the correct sign-in page on split-origin deploys. OAuth failure now redirects to the correct sign-in page on split-origin deploys. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Bugfix | Medium |
Admin nav highlight restored for Users, Companies, Settings in sidebar. Admin nav highlight restored for Users, Companies, Settings in sidebar. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: low |
— |
| Bugfix | Medium |
Admin navigation sidebar correctly highlights Users, Companies, and Settings entries after routing. Admin navigation sidebar correctly highlights Users, Companies, and Settings entries after routing. Source: granite4.1:30b@2026-05-21-audit Confidence: low |
— |
| Refactor | Medium |
Auth router rebuilt around a single state machine replacing hand-rolled if-chain. Auth router rebuilt around a single state machine replacing hand-rolled if-chain. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Refactor | Medium |
Removed hand-rolled <Card> blocks; introduced reusable <AuthCard> shell across auth pages. Removed hand-rolled <Card> blocks; introduced reusable <AuthCard> shell across auth pages. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Refactor | Medium |
Dropped Auth.redirectUrl field and LOGIN_REDIRECT_URL env var; SPA now decides post-login destination. Dropped Auth.redirectUrl field and LOGIN_REDIRECT_URL env var; SPA now decides post-login destination. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Refactor | Low |
Routes reorganized into a nested RouteObject tree with React.lazy per‑page chunks; page‑area providers mount once at user‑area parent. Routes reorganized into a nested RouteObject tree with React.lazy per‑page chunks; page‑area providers mount once at user‑area parent. Source: granite4.1:30b@2026-05-21-audit Confidence: low |
— |
| Refactor | Low |
Dropped legacy SignInContext, RegistrationContext, and InviteContext; data flows through useFormContext() and props instead. Dropped legacy SignInContext, RegistrationContext, and InviteContext; data flows through useFormContext() and props instead. Source: granite4.1:30b@2026-05-21-audit Confidence: low |
— |
Full changelog
This release polishes the sign-in flow and the routing layer that supports it. Auth pages now respect the user's locale, sign-in remembers the page the user was trying to reach before being bounced, and the app lands on an environment the user actually
has access to instead of the hardcoded /env/1/flows. Under the hood the auth router is rebuilt around a single state machine and @usertour/hooks's monolithic gql.ts gets its first domain split.
What's Changed
🌐 Localization on auth pages
Eight auth pages and their shared components — sign-in, sign-up, registration, invite, password reset, set-up admin, and the two 2FA screens — now go through useTranslation('ui') under a new auth.* namespace. Switching to zh-Hans flips every label,
button, placeholder, and validation message; English remains the default.
🔗 Deep-link return after sign-in
When a not-yet-logged-in user opens a deep link (e.g. a /env/X/users URL shared from elsewhere), they're bounced to sign-in with the original URL preserved as ?next=…. After signing in, they land back on the original page instead of the default
home. Same applies on the way through 2FA — ?next= is carried across the challenge step.
🧭 Environment-aware landing
The "where do I go after sign-in?" decision is no longer a hardcoded env id baked into server config. The SPA now picks the landing env from useAppContext().environment → localStorage → primary env → first env in the user's list, so a user who only
belongs to env 7 is no longer dumped on env 1.
🪟 404 stays inside the admin shell
Hitting an unknown URL while logged in used to drop the user on a fullscreen blank 404 with no way back to the app. The 404 now renders inside the same shell, with the sidebar still visible, so navigation is one click away. Hitting an unknown URL while
not logged in funnels through the same sign-in flow as any other protected page (preserving ?next=); hitting it on a still-being-set-up self-host instance redirects to /auth/setup-admin like the rest of the routes.
🎨 Sign-in visual refresh
The sign-in / sign-up / 2FA / password-reset cards now sit on a subtle grid-and-glow background keyed off the site's brand HSL variable, replacing the flat indigo gradient. Adjusting the brand colour in the future will carry these pages along
automatically.
🐛 Fixes
- Admin nav highlight restored. Users / Companies / Settings were no longer highlighted in the sidebar after navigating into them. Fixed by switching active-state detection from the (now wrong) inner-route id to URL pattern matching.
- OAuth failure lands on the sign-in page, not the API. Split-origin deploys (API and SPA on different hosts) used to dump OAuth-failure traffic onto a non-existent
/auth/signinroute on the API host. The redirect now prefixes the SPA host
correctly.
🛠️ Under the hood
The apps/web auth surface was reorganised end-to-end. The bullets above are the visible deltas; here's the architectural shape behind them:
- The hand-rolled
CustomRouteif-chain inroutes/index.tsxis replaced by<AuthGuard mode='guest' | 'user' | 'setup'>, a single three-mode state machine that owns every auth-related redirect (setup-admin enforcement, sign-in bounce with?next=,
2FA enrolment).routes/config.tsbecomes a nestedRouteObjecttree withReact.lazyper-page chunks; page-area providers (Environment / Attribute / Subscription) mount once at the user-area parent and stop remounting on every navigation. - Seven hand-rolled
<Card>+<CardHeader>blocks across the auth pages collapse into one<AuthCard>shell that owns the title chrome, description, footer slot, and loading skeleton. The three legacy React contexts that shadowedreact-hook-form's
<Form>(SignInContext / RegistrationContext / InviteContext) are dropped — the same data flows throughuseFormContext()and props. - The
Auth.redirectUrlfield on the GraphQL schema and theLOGIN_REDIRECT_URLenv var that fed it are gone. The SPA now owns the post-login destination decision:?next=(validated as same-origin) wins, otherwiseLandingRedirectresolves the env.
OAuth callbacks redirect to the SPA root through the same handler. packages/hooks/src/hooks/gql.tshad grown to 1306 lines; the auth domain (13 hooks + 3 new mutation wrappers) splits out to a newhooks/auth.tsmodule. The why, and the triggers that should pull more domains out in the future, are documented in
docs/adr/0002-hook-domain-boundary.md. The package also gets a README with the decision tree for adding new hooks.
Full Changelog: https://github.com/usertour/usertour/compare/v0.7.7...v0.7.8
Breaking Changes
- Removed `Auth.redirectUrl` GraphQL field and the `LOGIN_REDIRECT_URL` env var; post‑login destination is now handled client‑side.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About usertour
Usertour is an open-source user onboarding platform. It allows you to create in-app product tours, checklists, and surveys in minutes—effortlessly and with full control.The open-source alternative to Userflow and Appcues
Related context
Related tools
Beta — feedback welcome: [email protected]