Skip to content

Get started

Getting started

Nuxter is a Nuxt 4 app for Cloudflare Workers with auth, organizations, payments and the rest of a product's plumbing already built. You switch those parts on and off in starter.config.ts(Licensees only), build your product in the same repository, and pull in kit updates with one command.

What you get

The database is Postgres through Drizzle: Hyperdrive in production, PGlite on your machine (Database). The UI is Nuxt UI.

Requirements

  • Node 22.19+, 24.11+ or 26+ (engines in package.json)
  • pnpm 11 (packageManager in package.json(Licensees only) pins the exact version)
  • Access to the kit repository, nuxter-app/kit on GitHub

You need a Cloudflare account only to deploy, or to call AI models from pnpm dev.

Create your app

Your app gets its own repository and keeps the kit as a second git remote named template. That remote is where updates come from.

On GitHub, click "Use this template" on the kit repository, clone the new repository, and add the remote:

git remote add template https://github.com/nuxter-app/kit.git

To host the repository anywhere else, clone the kit and drop its history:

git clone https://github.com/nuxter-app/kit.git my-app
cd my-app
git update-ref -d HEAD
git commit -m "chore: start from the template"
git branch --unset-upstream
git remote rename origin template
git remote add origin <your repository>

Either way, keep your first commit identical to the kit and make your changes in the commits after it. The first update compares against that commit to find the kit version you started from. To start the app in a folder of a monorepo, see Template.

Run it locally

pnpm install
pnpm db:migrate
pnpm db:seed
pnpm dev

pnpm install also runs wrangler types and nuxt prepare; nothing typechecks until it has. pnpm db:migrate creates a PGlite database in .data/pglite so the seed has tables to write to. From then on, pnpm dev migrates it as it starts and serves it on 127.0.0.1:5432, next to the app on http://localhost:3000. If something else holds 5432, such as another project's dev server or a Postgres of your own, pnpm dev takes the next free port up to 5441 and logs which one.

pnpm db:seed adds 50 accounts, all with the password seed-password-123. With the shipped config each one also owns an organization. Three have fixed addresses:

AccountRole
admin@example.comsuperadmin
author@example.comstaff
user@example.comuser

pnpm db:seed --help lists its options, such as --count and --reset. It only writes to a database on your machine.

What runs without credentials

A fresh clone needs no .env and no Cloudflare login. The first pnpm dev writes a random NUXT_SESSION_PASSWORD to .env for you.

PartWith nothing configured
KV, R2, Queues, Durable ObjectsWrangler's local simulators
EmailPrinted to the terminal, including verification and reset links
TurnstileCloudflare's always-pass test keys
Workers AIOff. Run pnpm exec wrangler login, then set NUXT_DEV_REMOTE_AI=true in .env
Stripe checkout and webhookAnswer 500 until NUXT_PAYMENTS_STRIPE_SECRET_KEY and NUXT_PAYMENTS_STRIPE_WEBHOOK_SECRET are set
OAuthNone listed in auth.oauth. Each provider you add needs its client id and secret in .env

Payments are on as shipped, so a route that needs a plan permission (insights:read in the shipped config) answers 402 to a user whose plan does not grant it, with or without Stripe keys. To try a paid feature without Stripe, sign in as admin@example.com, grant user@example.com a plan on /dashboard/customers, then sign in as that user and open their organization.

Add variables to .env as you turn things on. .env.example(Licensees only) lists every one the kit reads and where each value comes from.

Your first superadmin

On an empty database, the first account to sign up becomes superadmin once it verifies its email address. Locally, the verification link is in the terminal. On a new deploy, register your own account first.

This happens only while no account holds users:manage, so after pnpm db:seed it never fires: sign in as admin@example.com instead. Set access.firstAccountRole to false in starter.config.ts to turn it off.

Where your code goes

PathWhat goes there
starter.config.ts(Licensees only)Which parts and providers are on, plans, roles, permissions, locales
app/(Licensees only)Pages, components, layouts, composables. The kit's pages are examples to delete or replace
server/api/(Licensees only)Your API routes, next to the kit's
server/jobs/(Licensees only)Background jobs, one file each
server/listeners/(Licensees only)Event listeners, one file each
server/database/custom/schema.ts(Licensees only)Your tables. pnpm db:generate writes their migrations
server/<part>/adapters/custom/A provider of your own for email, payments, AI, flags or monitoring. The filename is its id
shared/(Licensees only)Types, schemas and helpers both sides import. Add yours as new files
content/, i18n/locales/Blog posts, legal pages, translations

Everything else is the kit's: the other directories under server/, modules/, build/, emails/, test/. You can edit them, but when an update changes the same lines you resolve a conflict. Layout maps the whole tree.

Everyday commands

CommandWhat it does
pnpm devApp and local database
pnpm db:generateWrites a migration for changes in custom/schema.ts
pnpm db:migrateApplies pending migrations to the local database
pnpm db:studioDrizzle Studio on the local database, while pnpm dev is running
pnpm test --runThe unit and nuxt test suites
pnpm lint && pnpm format:check && pnpm typecheck && pnpm test --runWhat CI runs on every pull request

Take kit updates

git switch -c template-update-$(date +%Y%m%d)
pnpm template:update

The update applies everything the kit changed since your last one as a single commit, chore(template): update to …. Push the branch and review it as a pull request. If you and the kit changed the same lines, it stops with conflict markers: resolve them and run git cherry-pick --continue, or git cherry-pick --abort to back out. Template covers release tags, monorepos and which files conflict.

Good to know

  • The remote must be named template. pnpm template:update looks for it by that name.
  • pnpm dev stops when a port pinned with NUXT_DEV_PGLITE_PORT is taken, or when 5432 to 5441 all are. Its error says what to do (Database).
  • A DATABASE_URL exported in your shell outranks .env for the dev server and the database scripts. If it is production's, unset DATABASE_URL.
  • After pnpm install, a commit hook checks messages against Conventional Commits (feat: …, fix(auth): …, header up to 72 characters).

Next

  • Configuration: every key in starter.config.ts.
  • Deployment: the Cloudflare resources to create, the secrets, and the deploy itself.
  • Template: updates, releases and what conflicts.

A link with a lock opens the kit’s private repository, which every licensee can read.