Deployment
Deploy a Nuxt and Convex application with the correct SSR, realtime, and authentication boundaries.
Deploy Convex and Nuxt as two coordinated services. Convex owns the database and functions. Nuxt owns rendering, browser delivery, server routes, and the same-origin auth proxy.
Choose a supported topology
The normal topology is:
- a Convex cloud deployment;
- a Nuxt deployment with Nitro server support;
- one public HTTPS origin for the Nuxt application;
- browser access to Convex HTTPS and WebSocket endpoints.
Authentication requires an explicit convex.auth object and the generated /api/auth/* Nitro route. A fully static host without Nitro is not a supported auth topology. An app that omits auth can use Nuxt's static output, but only after its own SSR and client-navigation behavior is verified. Use auth: false only when a Nuxt layer must erase inherited auth configuration.
Deployment order
- Deploy the Convex schema, functions, HTTP routes, and auth component.
- Set the Convex
SITE_URL,BETTER_AUTH_SECRETS, andBCN_AUTH_PROXY_IP_SECRETvariables. Convex injects its deployment-ownedCONVEX_SITE_URLbuilt-in automatically. - Run the internal
auth:rotateSigningKeyoperator action before admitting auth traffic. - Build and deploy Nuxt behind a closed traffic gate, then verify the returned
newKidis present in public JWKS. - For delegated OAuth, provision and verify clients, resources, and links through the provider-owned admin API.
- Verify the deployed origins and auth ceremony, then open public ingress.
pnpm exec better-convex-nuxt-convex deploy
pnpm buildThe owner-only .env.local used here must contain either the intended
production deployment's scoped CONVEX_DEPLOY_KEY (or its supported alias) or
an exact self-hosted URL/admin-key pair. The checked runner rejects a plain
CONVEX_DEPLOYMENT for deploy, because the pinned CLI interprets that value as
project context and silently targets the project's production deployment.
Inspect the deployment-scoped key immediately before the command. Ambient,
sibling-file, project-key, preview-project-key, and command-line target
overrides are rejected.
Production checklist
- Use the exact Node, Nuxt, and Convex tuple in the package manifest. When auth is enabled, install the exact Better Auth and OAuth Provider optional peers explicitly.
- Set an exact HTTPS
SITE_URLwithout a trailing path and pass that same value asconvex.auth.origin. - Keep
BETTER_AUTH_SECRETSout of Nuxt entirely and keepBCN_AUTH_PROXY_IP_SECRETout of public config and logs. - Configure Nuxt's
NUXT_PUBLIC_CONVEX_SITE_URLto the exact deployed HTTP Actions origin; do not try to override Convex's built-inCONVEX_SITE_URL. - Confirm
/api/auth/*reaches the intended.convex.siteorigin. - Permit the exact Convex HTTPS and WebSocket origins in Content Security Policy.
- Configure
convex.auth.trustedClientIpHeaderoutside exact loopback development and make the ingress overwrite it with exactly one client IP. Missing or malformed values fail closed before Better Auth. - Restrict direct access to the Nuxt origin so public traffic can arrive only through that ingress, or independently authenticate ingress requests at the origin. A rewritten header is not a boundary when the origin is bypassable.
- Keep module logging off unless investigating a specific problem.
- Exercise sign-in, sign-out, SSR refresh, client navigation, and realtime reconnect.
- Verify backend authorization with two different users, not only UI visibility.
- Rehearse social-provider callbacks, recovery, expiry, denial, and rollback for every enabled provider.
- For delegated OAuth/MCP, also rehearse consent, PKCE, wrong-client/resource/scope rejection, revocation, and live membership removal.
The delegated OAuth and MCP guide defines the pre-traffic key ceremony, fixed topology, deployment order, and forward-fix recovery policy. Do not replace it with first-request key creation or destructive JWKS cleanup.
Preview deployments
An arbitrary preview URL cannot safely reuse production auth configuration. Give stable previews their own Convex deployment, exact SITE_URL, and independent secrets, or disable auth for documentation-style previews. Wildcard trusted origins and shared production secrets weaken the boundary and are not a substitute for isolated environments.
Health checks
A successful HTML response proves only that Nuxt started. Add checks that cover the actual dependency chain:
- an anonymous Convex query;
- an authenticated server-rendered page when auth is enabled;
- a browser subscription receiving a change;
- the auth proxy rejecting unsupported methods and invalid upstream behavior.
See Security Model before exposing the application publicly.