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