Setup guide
An idempotent, no-nuke setup. Five steps take you from a cloned template to a live, admin-controlled site backed by Convex.
You never delete the Convex project
Every step here is safe to repeat. If something is misconfigured — a wrong env var, a missing key, a half-finished deploy — the fix is to re-run these steps, not to delete and recreate the Convex project. The build only writes what is missing, so re-running converges to a correct state instead of starting over.
Grab your Convex URL + a full-permission deploy key
In the Convex dashboard, open your project and copy the deployment URL. Then generate a production deploy key with full permissions:
deployment:deploy— push functions & schemaenv:view— read existing backend env varsenv:write— let the build provision auth env vars for you
The
env:writescope is what makes the auth bootstrap (step 4) zero-touch. A read-only key will make the build fail trying to write JWT keys.Set the two env vars in Vercel
In your Vercel project → Settings → Environment Variables, add both for the Production environment:
NEXT_PUBLIC_CONVEX_URL=https://<your-deployment>.convex.cloud CONVEX_DEPLOY_KEY=<your-full-permission-deploy-key>NEXT_PUBLIC_CONVEX_URLis what the browser uses to talk to Convex;CONVEX_DEPLOY_KEYis what the build uses to deploy the backend beforenext buildruns.Pick how the first admin gets created
A fresh Convex backend has an empty users table, so it needs exactly one first admin. Choose either path:
A. Zero-touch (set env vars)
Set these in your Convex env (dashboard → Settings → Environment Variables). The first admin is created automatically on deploy:
ADMIN_EMAIL=you@example.com ADMIN_PASSWORD=<a-strong-password>B. Claim ownership in-app
Skip the env vars. After deploy, visit
/dashboard/adminand click Claim ownership — the first account to sign up becomes the admin.Push — the build provisions auth and deploys
Push to your default branch (or hit Deploy in Vercel). The build command runs three steps in order, all idempotent:
setup-auth # provisions JWT_PRIVATE_KEY, JWKS, SITE_URL in Convex convex deploy # pushes schema + functions to your backend next build # builds the Next.js app with NEXT_PUBLIC_CONVEX_URLsetup-authonly writes env vars that are missing, so re-running it never rotates keys or breaks existing sessions.Optional — load sample data
Want content to look at before adding your own? Sign in as the admin and click Load sample data in the admin panel, or run the seed from your machine:
npx convex run seed:runThe seed is idempotent too — re-running it tops up missing rows rather than duplicating everything.
Why does my fresh clone look read-only?
Because it is — on purpose. A fresh Convex backend ships with an empty users table. Until you become the first admin — by setting ADMIN_EMAIL / ADMIN_PASSWORD (step 3A) or by signing up and claiming ownership (step 3B) — there is no authenticated user, so every edit and mutation is blocked.
That locked-down state is expected, not a bug. As soon as the first admin exists, the dashboard becomes fully writable. Nothing to delete, nothing to recreate — just finish step 3.