Installation
Get the Nuxt template running on your machine.
This guide takes you from a fresh clone to the app running at
http://localhost:3000.
Prerequisites
- Node.js 20 or later — use an active LTS release. The Dockerfile builds on Node 22, which is the recommended version.
- pnpm — the project's package manager (
packageManager: pnpm@10.18.3). Enable it withcorepack enableor install it from pnpm.io. - PostgreSQL — a local or hosted database you can connect to. You only need
a reachable
NUXT_DATABASE_URL.
Only a database is required to boot. Email, OAuth, payments, and AI each need their own keys, but the app starts without them — those features stay inactive until configured. See Environment Variables.
Setup
Install dependencies
pnpm installThis also runs nuxt prepare via the postinstall script, which generates the
.nuxt/ types and auto-import declarations.
Create your environment file
Copy the example and fill in at least the database and Better Auth values:
cp .env.example .envThe minimum to boot locally:
NUXT_DATABASE_URL— your PostgreSQL connection string.NUXT_BETTER_AUTH_SECRET— a random secret. Generate one withopenssl rand -base64 32.NUXT_PUBLIC_BASE_URL—http://localhost:3000for local development. This drives Better Auth'sbaseURLandtrustedOrigins.
Everything else is optional for a first run. See Environment Variables for the full reference.
Initialize the database schema
This template uses a generate/migrate workflow. Generate the SQL migrations from the Drizzle schema, then apply them:
npx drizzle-kit generate
npx drizzle-kit migrateThe Drizzle config lives at server/database/drizzle/drizzle.config.ts and reads
NUXT_DATABASE_URL from the Nuxt runtime config. The first generate creates
the migrations folder; migrate creates the auth and payment tables. See
Database for the schema and production notes.
Start the dev server
pnpm devOpen http://localhost:3000. The dev script runs
nuxt dev --host, which also exposes the app on your LAN — add any extra LAN
origin to NUXT_AUTH_EXTRA_TRUSTED_ORIGINS if Better Auth rejects it.
Verify the installation
Work through this checklist to confirm each layer is wired:
- Homepage loads at
http://localhost:3000. - Database connects — no connection errors in the terminal, and
drizzle-kit migratecompleted without error. - Registration — create an account at
/auth/register. - Email verification — registration requires a verified email. Without Resend configured, the verification email won't send and login is blocked. See the note below.
- Dashboard — after verifying and logging in,
/dashboardis reachable.
Email verification is required by default
(requireEmailVerification: true in server/utils/auth.ts). If
NUXT_RESEND_API_KEY is not set, the verification email cannot be delivered
and the new account cannot log in. For local testing, configure Resend
(Email) or temporarily relax this setting in
server/utils/auth.ts.
Package scripts
These are the scripts defined in package.json:
| Command | What it does |
|---|---|
pnpm dev | Start the Nuxt dev server (nuxt dev --host) |
pnpm build | Production build (Nitro .output) |
pnpm generate | Static site generation |
pnpm preview | Preview the production build locally |
pnpm postinstall | Run nuxt prepare (auto-runs after install) |
Lint with ESLint:
pnpm eslint .Database commands
Drizzle Kit is invoked directly; these are commands, not package scripts:
| Command | What it does |
|---|---|
npx drizzle-kit generate | Generate SQL migrations from the schema |
npx drizzle-kit migrate | Apply pending migrations to the database |
npx drizzle-kit studio | Open Drizzle Studio to browse data |
Common first-run failures
| Symptom | Likely cause | Fix |
|---|---|---|
Connection refused / ECONNREFUSED on boot | NUXT_DATABASE_URL missing or PostgreSQL not running | Start PostgreSQL and verify the URL |
| Auth errors / invalid session | NUXT_BETTER_AUTH_SECRET missing or changed | Set a stable secret in .env |
| Can't log in after registering | Email verification required but Resend not configured | Configure NUXT_RESEND_API_KEY or relax verification locally |
| OAuth buttons do nothing or error | GitHub/Google credentials not set | Configure the provider or hide its button — see Authentication |
