New Ory Agent Security is now live! Claim your complimentary test drive. Get Started!

Skip to main content

TanStack Start Quickstart

This quickstart sets up Ory Elements in a TanStack Start application with @ory/tanstack-start.

info

The code used in the following quickstart is available in the TanStack Start example GitHub repository

How it works​

TanStack Start runs route loaders on the server for the first request and in the browser on client-side navigation. To always send the browser's Ory cookies, the app fetches flows in server functions. @ory/tanstack-start provides the helpers that run inside them.

During local development and on preview deployments, a request middleware serves Ory on the app's own origin, so Ory's cookies are first-party. The middleware isn't supported in production: through the middleware, Ory sees your app server as the client instead of your users' browsers. In production, use a custom domain on Ory Network, or serve Ory on your own domain with the Ory Enterprise License, on the same site as your app.

Prerequisites​

  1. Create a TanStack Start application by following the TanStack Start getting started guide. This quickstart assumes the default src/ layout with file-based routes in src/routes.

  2. Install the @ory/elements-react and @ory/tanstack-start packages.

    npm install @ory/elements-react @ory/tanstack-start

Set up Ory Elements​

  1. Set the URL of your Ory project in the .env file. The server reads ORY_SDK_URL and ORY_PROJECT_API_TOKEN; the browser never sees them.

    You can find your Ory Network project URL in the Get started section of the Ory Console. ORY_PROJECT_API_TOKEN is optional. The proxy needs it for OIDC and SAML redirects. For preview deployments, create a dedicated API key, set it only in the preview environment, and never give it a VITE_ prefix.

  2. Add the configuration for Ory Elements. Create src/ory.config.ts:

    src/ory.config.ts

  3. Define the server functions. Create src/ory.functions.ts. Each flow function validates the route's search params and returns the flow, or redirects the browser to Ory when the flow must be created or restarted. oryBaseUrlFn returns the URL where the browser reaches Ory, from getOryBaseUrl.

    src/ory.functions.ts

    Define each server function in your app, assigned to a top-level variable as shown. TanStack Start's compiler finds server functions by that variable.

  4. Register the request middleware. Create src/start.ts. The CSRF middleware rejects cross-site calls to your server functions. Once src/start.ts defines a startInstance, TanStack Start no longer adds its default CSRF middleware, so keep it in the list. Set trustedOrigins to the origins your local development server and preview deployments serve.

  5. Load the base URL in the root route and add the Ory Elements styles. Update src/routes/__root.tsx, and create src/use-ory-base-url.ts to read the base URL in the pages:

    src/routes/__root.tsx

  6. Create a route for each self-service flow in src/routes: login.tsx, registration.tsx, recovery.tsx, verification.tsx, and settings.tsx. Each route passes its search params to the server function with loaderDeps, so the loader runs again when the flow param changes. The flow carries the URL where the browser reaches Ory, so each page passes only the flow to the Ory Elements component. The settings page passes the base URL from the root route as baseUrl to SessionProvider.

    src/routes/login.tsx

  7. Show the session and a logout link on the home page. Update src/routes/index.tsx:

    src/routes/index.tsx

  8. Run the application on port 3000, the origin listed in trustedOrigins:

    npm run dev

    Open http://localhost:3000/registration to create your first user. The other flows are at /login, /recovery, /verification, and /settings.

Preview deployments and production​

Keep the middleware registered in every environment. On a preview deployment, it serves Ory on the preview's origin when that origin is in trustedOrigins. Add a glob for your preview hosts that includes your team, for example https://my-app-*-my-team.vercel.app.

An entry in trustedOrigins is an origin without a path, such as http://localhost:3000. To match several origins, use * in the host as a glob. Each * matches one or more letters, digits, or hyphens and never a dot, so it stays inside one part of the host name. A * can't make up the whole label right before a public suffix from the Public Suffix List, such as vercel.app or com, so https://*.vercel.app is rejected. On a hosting provider's domain, include your project and team in the glob, so it doesn't match other customers' deployments. The proxy reports the app origin to Ory only for the origins in trustedOrigins. For any other origin, the app uses the Ory SDK URL and logs a warning. Don't add your production origin. See Trusted origins for more examples.

In production, Ory runs on a custom domain on the same site as your app, so the app uses ORY_SDK_URL whether the middleware is registered or not.

The flow, session, and base URL functions mark their responses Cache-Control: private, no-store. On pages that are not 2xx, such as a 404, they do so only when the middleware is registered. Don't let a shared cache, such as a CDN rule that caches every page, store flow pages or server function responses.

The browser reaches Ory on the app's origin when the middleware handled the request, the origin is in trustedOrigins, and Ory is on another site, and on ORY_SDK_URL otherwise.

Troubleshooting​

When the browser would call Ory on another site, Ory's session cookies don't reach the app, and login or session checks fail. @ory/tanstack-start then logs a warning once in the server log:

WarningFix
The Ory proxy handled a request for <origin>, which is not in trustedOriginsIn local development or a preview deployment, add the origin to trustedOrigins. In production, use a custom domain on the app's site.
The app (<origin>) and Ory (<url>) are on different sitesThe proxy didn't run for this request. Register oryProxyMiddleware in src/start.ts and call the helpers from server functions.
The request's Host header is not a valid originConfigure the reverse proxy in front of the app to forward the Host header the browser sent.

Next steps​

Customize the components, add your own styles, and integrate them into your application. See Theming to change the look and feel of the components.