Skip to main content
By the end of this page your Next.js app has Sign in with Fanvue: login, callback and logout routes, a signed cookie session, and an API client that refreshes its tokens when they expire. Everything imports from @fanvue/builder-sdk/nextjs/off-platform. You need:
  • an off-platform app in the Developer Area, with its Client ID and Client Secret
  • a Next.js App Router project with @fanvue/builder-sdk and next 14 or later installed
  • an https origin for your dev server, unless it runs on localhost

Run over HTTPS locally

A redirect URI uses https:// on any host, or http:// only on localhost, 127.0.0.1 or [::1]. The examples in this guide use my-fanvue-app.dev, which is neither, so give your dev server an https origin with portless, or with mkcert and local-ssl-proxy. Set up local HTTPS proxy walks through both. Use the resulting URL, for example https://my-fanvue-app.dev:3001/api/auth/callback, as the redirect URI in your app registration and in OAUTH_REDIRECT_URI. If you use an App Manifest, it can’t live on the local hostname, because Fanvue reads it from a public domain. Serve it from your production or staging domain and list the local redirect URI in oauth.redirectUris alongside the production one.

Configure the client

createConfig(opts?) resolves your OAuth client from options or environment variables and throws when a required value is missing. createConfigSafe(opts?) returns { ok: false, missing } instead, naming the unset variables, so a route can answer 503 on a misconfigured deployment. Both read the same variables, listed in full under Environment variables. The SDK’s default callback path is /api/auth/callback, which differs from the /api/oauth/callback used by the App Starter. Register whichever your routes serve.
.env.local
OAUTH_SCOPES adds to the default openid offline_access offline, so list only the Fanvue scopes your app needs. Every scope must be registered on your app’s Authentication tab or in its App Manifest.

Add the route handlers

Each handler factory takes an OffPlatformOptions object, which is the resolved config plus afterLoginPath and afterLogoutPath. Both paths are required, and both accept null, which means /. Build one options object and share it across the three routes.
lib/fanvue.ts
app/api/auth/login/route.ts
app/api/auth/callback/route.ts
app/api/auth/logout/route.ts
Register the callback route’s full URL, including scheme and port, as the redirect URI. Any mismatch fails the token exchange.

Read the session

After sign-in, the callback stores a signed JWT in an httpOnly cookie. The JWT holds the access token, refresh token and expiry, plus the creator’s uuid, handle, displayName, isCreator and avatarUrl. getSession(secret, cookieName?) verifies the cookie and returns the SessionPayload, or null when the cookie is missing or fails verification. getAuthenticatedClient({ sessionSecret, sessionCookieName, config }) returns a FanvueClient bound to the session’s access token, or null when there is no valid session. When the access token is within 30 seconds of expiry and a refresh token exists, it refreshes first and rewrites the cookie with the new tokens. A failed refresh also returns null, so treat null as a signal to send the creator to /api/auth/login.
app/home/page.tsx
A creator who signs in through this flow grants offline access, so the refresh token in the cookie keeps the session alive for the full 30 days without a new login. For what the client can do, see Call the API with the SDK client.

Receive webhooks

Webhook subscriptions are created with the creator’s OAuth token, which this entrypoint produces, so it re-exports createWebhookReceiverHandler and its port types. Receive webhooks with the SDK covers the setup.

Troubleshoot

See also