Skip to content

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.

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.

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.

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>
);
}

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.

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.

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 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.