Hosted portal overview
Shrines is Torii’s hosted portal: ready-made sign-in, sign-up, and account pages that Torii serves for you. Every environment has them, they are on by default, and they need no UI code — you link to them and users come back signed in.
The pages render the same components the SDK ships
(<SignIn> and <UserProfile>),
in your brand colors. If you would rather mount those yourself, see
hosted pages or your own UI.
The pages
Section titled “The pages”| Page | Path | What it does |
|---|---|---|
| Sign in | /sign-in |
Opens the auth card on sign-in. Footer links reach sign-up and forgot-password. |
| Sign up | /sign-up |
The same card, opened on sign-up. |
| Account | /user |
The user’s profile when signed in; the auth card when not. |
/sign-in and /sign-up are one card in two starting states, not two pages. A user
who lands on /sign-in and follows the Sign up footer link switches in place —
and still gets your sign-up redirect target, because
the destination follows the flow they completed, not the URL they arrived on.
Any other path (/, /user, anything unrecognized) shows the account page.
Where they’re served
Section titled “Where they’re served”The portal always sits on a dedicated host, never on your Frontend API host. Which host depends on how far domain setup has gone:
| State | Portal host |
|---|---|
| Sandbox | your Torii host, e.g. your-app-name.shrines.dev |
| Production, custom domain not verified | your Torii host, as above |
| Production, custom domain verified but portal domain not | your Torii host, still |
| Production, portal domain verified | shrines.yourdomain.com |
Note the third row: verifying your custom domain moves the Frontend API to
torii.yourdomain.com, but not the portal. The portal needs its own DNS record and
its own verification step — your own domain
walks through it, and it is what makes the session readable by your app’s other
subdomains.
Linking to it from your app
Section titled “Linking to it from your app”Send unauthenticated users to /sign-in on the portal host, with a redirect_url
pointing back to where they should land:
import { SignedOut } from '@torii-js/torii-react';
const PORTAL = 'https://shrines.yourdomain.com';
function SignInButton() { const target = `${PORTAL}/sign-in?redirect_url=${encodeURIComponent(window.location.href)}`; return <a href={target}>Sign in</a>;}
export function Header() { return ( <SignedOut> <SignInButton /> </SignedOut> );}<a href="https://shrines.yourdomain.com/sign-in?redirect_url=https%3A%2F%2Fapp.yourdomain.com%2Fdashboard"> Sign in</a>redirect_url is honored only when it points at one of your allowed origins —
otherwise the user lands on your configured fallback instead. That, and the full
precedence order, is covered in redirects.
What the pages look like
Section titled “What the pages look like”The card renders in your environment’s brand colors and color scheme, set under Project → Shrines → Customization. Four knobs: color mode, primary color, background color, and whether to hide the Torii footer. See appearance.
Deeper customization — element overrides, custom labels, your own layout — is available when you mount the components in your own app, not on the hosted pages.
Turning the portal off
Section titled “Turning the portal off”Once your own sign-in pages are live you can switch the hosted ones off, under Project → Shrines → Overview. Disabling requires four values, so that anything pointing at the portal has somewhere to go instead:
- your application host, e.g.
app.example.com - your sign-in path, e.g.
/sign-in - your sign-up path
- your sign-out path
With the portal off, its URLs return a genuine 404 — not a page that says “not found”. Anything that still links to them fails visibly rather than silently showing users an empty auth screen.
Re-enable it at any time; nothing is destroyed by turning it off.
OAuth and the portal
Section titled “OAuth and the portal”OAuth providers work on the hosted pages with no extra configuration: the callback lands on your Frontend API host as usual, and the portal completes the handoff back to your app. The redirect URL you register with the provider is the same one you would register otherwise — the portal does not add a second callback.