Nextbase Docs
Nextbase Docs
HomeBlogWelcome to Nextbase v5!Choose your starterGetting startedLocal Supabase per agent
TanStack + ConvexInstallationEnvironment variablesAuthenticationAgent connectionsProject structureDeployment
AuthenticationWorkspaces and the admin area
Building with agentsEmails with Resend
TroubleshootingNextbase v5
The 8 starter kitsTanStack + Convex

Installation

Run the TanStack + Convex starter locally with the Convex local backend, Convex Auth, the web app and the admin app.

This page takes you from a fresh clone to a signed-in account with a workspace, plus the admin app running on its own port. The whole flow runs on your computer; no Convex account or Docker is needed.

The shared getting started page covers the parts that are the same for every kit.

Clone the repository

git clone https://github.com/usenextbase/tanstack-convex-starter.git
cd tanstack-convex-starter

If GitHub says the repository doesn't exist, check that you are signed in with the account that has access.

Install dependencies

Use Node.js 24 (the version in .nvmrc; package.json engines requires >=24) and let corepack select pnpm 10.33.0 from the packageManager field.

corepack enable
pnpm install

Create and select the local Convex backend

Copy the example env file first, then create and select the local deployment:

cp .env.local.example .env.local
pnpm db:local:init
pnpm db:local:select

db:local:init runs convex init with CONVEX_AGENT_MODE=anonymous, so no Convex login is needed. db:local:select runs convex deployment select local and fills in CONVEX_DEPLOYMENT, VITE_CONVEX_URL and CONVEX_SITE_URL in .env.local at the repository root. The backend state (rows, storage, schedules, function execution) lives in .convex/, which is gitignored.

Copying the example file first matters. When .env.local already contains a VITE_CONVEX_URL line, the CLI updates it. When the file does not exist, the CLI creates it with CONVEX_URL instead, because Vite is not a root dependency, and you have to add VITE_CONVEX_URL yourself. The dev:local guard accepts either name for its loopback check, but stops with a message telling you to add VITE_CONVEX_URL=http://127.0.0.1:3210 if only CONVEX_URL is present, because the web app reads the VITE_ name.

After the select step, the first lines of .env.local should look like this:

CONVEX_DEPLOYMENT=local:nextbase
VITE_CONVEX_URL=http://127.0.0.1:3210
CONVEX_SITE_URL=http://127.0.0.1:3211
APP_URL=http://localhost:3000

APP_URL is never generated; it comes from the example file. The example also sets VITE_ADMIN_APP_URL=http://localhost:3002 for the admin app link and MCP_APP_URL=http://localhost:3000 for the MCP consent page.

Don't copy the example file over an existing .env.local

.env.local.example documents every variable, but the Convex CLI maintains the deployment lines in .env.local. Copy the example only when you have no .env.local yet, and keep your own values if you already have one.

Configure the admin app

The admin app has its own env file because apps/admin/vite.config.ts sets envDir: ".". Copy its example and point it at the local backend:

cp apps/admin/.env.local.example apps/admin/.env.local
VITE_CONVEX_URL=http://127.0.0.1:3210
VITE_WEB_APP_URL=http://localhost:3000
VITE_OAUTH_PROVIDERS=

The example ships with a cloud placeholder for VITE_CONVEX_URL; replace it with the same local URL the web app uses. VITE_WEB_APP_URL is where impersonation handoffs and the "Open web app" link go.

Set up Convex Auth

pnpm auth:setup

This runs the @convex-dev/auth CLI against the selected deployment. It configures the auth signing keys (JWT_PRIVATE_KEY and JWKS) and SITE_URL in that deployment's environment. Password sign-in works after this step. Run it again if you create a new local deployment.

So the admin app can sign in on its own origin, also set the admin origin in the local deployment:

pnpm convex env set ADMIN_SITE_URL http://localhost:3002

Start the dev servers

pnpm dev:local

dev:local runs the guard, then starts four processes with concurrently: convex dev (local backend on http://127.0.0.1:3210, HTTP actions on http://127.0.0.1:3211), the web app, the admin app and the React Email preview server.

AppURL
Web apphttp://localhost:3000 (apps/web/vite.config.ts)
Email template previewhttp://localhost:3001
Admin apphttp://localhost:3002 (apps/admin/vite.config.ts); / redirects to /app-admin

To run only the admin app, use pnpm dev:admin. Keep the Convex process running while you use either app.

Seed reference data (optional)

In a second terminal:

pnpm db:seed

This runs dev/seed:seed, which inserts the product row in appSettings (product name and support email) once. It is idempotent.

Create your account and workspace

Open http://localhost:3000/sign-up and create an account with a name, email and password. The kit then sends a verification code and takes you to /update-password?mode=verify to enter it.

There is no local email inbox

Verification, password reset and magic link emails go through Resend even in local development. Set AUTH_RESEND_KEY and AUTH_EMAIL_FROM in the local deployment with pnpm convex env set NAME value to receive them. Without them, use a social provider you have configured, or see the authentication page for what works without email.

After signing in you land on /onboarding, complete your profile and create a workspace. Then add a project from the workspace's projects page so you have data to test with.

Verify the setup

Run the quality gates from the repository root:

pnpm format:check
pnpm lint
pnpm typecheck
pnpm test
pnpm build

pnpm test runs Vitest in each workspace (Convex functions use convex-test). pnpm test:e2e runs Playwright against http://127.0.0.1:3000; without PLAYWRIGHT_BASE_URL it starts its own local Convex backend and web server. Install the browser first with pnpm --filter @nextbase/web exec playwright install --with-deps chromium.

Make yourself an application admin

Set the admin email in the local deployment, sign in with that address on the admin app at http://localhost:3002, then use Claim admin access on /app-admin:

pnpm convex env set NEXTBASE_ADMIN_EMAIL admin@example.com

The admin app has its own login page and session; signing in to the web app does not sign you in to the admin app. The authentication page explains the claim flow.

Useful commands

CommandWhat it does
pnpm devSame as dev:local but without the local-deployment guard
pnpm dev:adminStarts only the admin app on port 3002
pnpm build:web, pnpm build:adminBuild one frontend without Turbo
pnpm db:codegenRegenerates apps/database/convex/_generated
pnpm db:typesRegenerates apps/database/lib/database.types.ts from the schema validators
pnpm db:statusOpens the Convex dashboard for the selected deployment
pnpm agents:syncRegenerates the AI coding tool files from AGENTS.md and .agents/; CI runs pnpm agents:check
pnpm convex run migrations:backfillUsersAggregateOne-time backfill of the users aggregate when upgrading an existing deployment

Stop and reset

Stop the dev servers with Ctrl+C; concurrently stops the other processes when one exits. The local data in .convex/ is kept between runs.

To reset the local backend, stop the servers and delete the .convex/ directory, then run pnpm db:local:init, pnpm db:local:select and pnpm auth:setup again. Deleting .convex/ removes every local row, upload and scheduled job, including the deployment environment variables you set with pnpm convex env set.

If a request fails after a branch change, check that convex dev is still running and that .env.local points at the local deployment. See troubleshooting.

TanStack + Convex

Overview of the TanStack Start + Convex starter: what it ships, what you need, and where to go next.

Environment variables

Every variable in the starter's two example env files, which runtime reads it, and where its value comes from.

On this page

Clone the repositoryInstall dependenciesCreate and select the local Convex backendConfigure the admin appSet up Convex AuthStart the dev serversSeed reference data (optional)Create your account and workspaceVerify the setupMake yourself an application adminUseful commandsStop and reset