convex-logto

Vite + React

Mount the provider in a Vite SPA. The Quick start, condensed to the Vite-specific pieces, for both modes.

The Quick start is the full Vite walkthrough. This page is the condensed reference for the two Vite-specific pieces, where the provider mounts and the callback route, in each mode.

Backend setup (Logto app + RSA key, Convex env, auth.config.ts) is the same for every framework; see Quick start steps 1 to 3.

Session mode

The provider talks to the logtoSessionApi(...) re-exports (api.auth below) and nothing else. No Logto config reaches the bundle.

src/main.tsx
import { ConvexReactClient } from "convex/react";
import { ConvexLogtoSessionProvider } from "convex-logto/react-session";
import { api } from "../convex/_generated/api";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL, {
  initialAuthTokenReuse: true,
});

root.render(
  <ConvexLogtoSessionProvider client={convex} sessionApi={api.auth}>
    <App />
  </ConvexLogtoSessionProvider>,
);

A plain SPA needs no navigate; the provider falls back to a hard replace after sign-in. Add navigate once you have a router, as the TanStack Router page does.

Callback route

The provider owns /callback. It POSTs the code to Convex and replace-navigates to afterSignIn itself, so the view you render there is only ever a flash:

src/App.tsx
if (window.location.pathname === "/callback") return <p>Finishing sign in…</p>;

A plain Vite SPA usually ships to a static host, which has no same-site server to mount the cookie transport on. That is fine; the default localStorage transport is the supported static-hosting path. The session token there rotates on every use, and the server stores only its hash. Add the cookie transport when you have a server on the same site, not before.

Full app: examples/vite-react-session.

Bridge mode

Bridge mode swaps the entry and the props. The mount point and the callback route are the same.

src/main.tsx
import { ConvexReactClient } from "convex/react";
import { ConvexLogtoProvider } from "convex-logto/react";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);

root.render(
  <ConvexLogtoProvider
    client={convex}
    config={{
      endpoint: import.meta.env.VITE_LOGTO_ENDPOINT,
      appId: import.meta.env.VITE_LOGTO_APP_ID,
    }}
  >
    <App />
  </ConvexLogtoProvider>,
);

The two VITE_LOGTO_* values are public. To keep them out of the bundle anyway, export logtoConfigQuery() from convex/logto.ts and pass configQuery={api.logto.config} instead of config.

The callback route is the same one-liner. Here the provider runs the SDK's code exchange on /callback and then navigates to afterSignIn.

Full app: examples/vite-react.

On this page