Valcraven Docs
Getting Started

Quickstart

Clone Valcraven and run the full dev stack locally with Docker Compose.

Get Valcraven running on your machine. The recommended path is Docker Compose — one command brings up the Next.js app, the realtime Worker (which hosts the AI agent), and a Caddy + Tailscale sidecar for HTTPS phone QA. Everything is wired together and hot-reloads on file changes.

Prerequisites

  • Docker (Docker Desktop or OrbStack) — the recommended path bundles everything.
  • Node.js 22+ and npm — required only if you want to run the app directly without Docker, or run tests/scripts on the host.
  • Git.

1. Clone and configure

git clone <your-repo-url>
cd valcraven
cp apps/web/.env.example apps/web/.env

Open apps/web/.env and set the one required value — an auth secret:

# In apps/web/.env
BETTER_AUTH_SECRET=<paste the output of: openssl rand -base64 32>

Everything else has a working default for local dev. BETTER_AUTH_URL and APP_URL default to http://localhost:3013 (set by Docker Compose), and the database is a local SQLite file. See Environment variables for the full getting-started subset, and /docs/reference/environment-variables for every variable.

Docker Compose reads apps/web/.env for the app's runtime variables. A few variables — TS_AUTHKEY, TS_HOSTNAME, and DEV_PORT — are consumed by Compose itself for the Tailscale sidecar; put those in a root-level .env next to docker-compose.yml. They're optional and only needed for phone QA (see below).

2. Start the dev stack

From the repo root:

# First run (or after changing dependencies / Dockerfiles): build the images
docker compose --profile dev build

# Start everything with hot reload
docker compose --profile dev up

Your app is now running at http://localhost:3013.

The dev profile starts three containers:

ServiceRole
caddy-devCaddy + Tailscale sidecar. Owns the host port (3013) and is the single front door: routes /agents/* and /realtime/* to the realtime Worker and everything else to Next.js. Also provides the HTTPS tailnet URL.
app-devThe Next.js app (apps/web) in full dev mode — hot reload, HMR, error overlay. Runs on internal port 3000 behind Caddy.
realtime-devThe realtime Worker (apps/realtime) under wrangler dev, hosting the AI agent (the AppAgent Durable Object). Answers at /agents/* (internal port 8788).

Source code is bind-mounted, so file changes appear automatically. You only need to rebuild an image when its dependencies (package.json) or Docker config change. To refresh a container's installed dependencies without a full rebuild: docker compose --profile dev run --rm app-dev npm ci.

3. Create an account

Visit http://localhost:3013/auth and sign up with email and password. Better Auth bootstraps its own tables on first use, so there is no default admin account and no separate seeding step for auth.

To promote a user to admin locally, add their email to ADMIN_EMAILS in apps/web/.env (comma-separated) and sign up — the signup hook promotes matching emails. To set a known password on an existing user without the email flow:

docker compose --profile dev exec app-dev \
  node scripts/reset-password.mjs <email> <new-password>

Database migrations

Valcraven uses SQLite locally (via Drizzle ORM). Better Auth's tables are created automatically on first access, so the app runs immediately. To apply the full set of schema migrations (apps/web/migrations/*.sql) — for example after you add a table — run the migrate script inside the container:

docker compose --profile dev exec app-dev npm run db:migrate

See Database migrations for how to author and generate migrations.

Running directly with Node (optional)

If you'd rather not use Docker, the repo is an npm workspace — run everything from the repo root, where the root package.json delegates each script to apps/web:

npm install          # installs all workspaces
npm run db:migrate   # apply migrations to local SQLite
npm run dev          # start the Next.js dev server

npm run dev starts only the Next.js app (Next's dev server, default port 3000) — it does not start the realtime Worker or the Tailscale sidecar. Because AI chat runs through the realtime Worker, start it separately with npm run dev:realtime if you need chat. For the complete without-Docker workflow, see the repo README.md → "Local Development (Without Docker)".

Remote dev — phone QA over HTTPS (Tailscale)

The caddy-dev sidecar can expose your local dev stack to your phone (or any device on your Tailscale tailnet) over real HTTPS — no public exposure, no ngrok. HTTPS is mandatory here: iOS Safari refuses plain HTTP on *.ts.net hostnames, and it also unlocks secure-context browser features (Web Speech, service workers, clipboard).

One-time setup:

  1. Install Tailscale on your Mac and your phone, signed into the same account.

  2. Get a Tailscale auth key at login.tailscale.com/admin/settings/keys.

  3. Add these to a root-level .env (next to docker-compose.yml):

    TS_AUTHKEY=tskey-auth-...
    TS_HOSTNAME=valcraven   # optional; this is the default
  4. Bring up the dev profile: docker compose --profile dev up.

From your phone, hit https://<TS_HOSTNAME>.<your-tailnet>.ts.net. The template already whitelists *.ts.net in Next.js's allowedDevOrigins (apps/web/next.config.ts) and in Better Auth's trustedOrigins (apps/web/lib/auth.ts), so HMR and sign-in work from the tailnet host.

OAuth from the tailnet: the OAuth state cookie is host-scoped, so a single BETTER_AUTH_URL serves exactly one host. To test OAuth from your phone, set BETTER_AUTH_URL to your tailnet HTTPS URL and register that callback with each provider. See OAuth setup. Full Tailscale details, including the iOS DNS gotcha, live in the repo README.md → "Remote Dev (phone QA via Tailscale)".

Next steps

On this page