Start

How to use the documentation and product routes.

WebsiteWebsite

Vercel deployment checklist

Environment, callback, migration, and verification checklist for deploying the active Miner auth and dashboard backend on Vercel.

#website/vercel-deployment
websitedeploymentvercelauthenvironment

Runtime and project settings

Deploy the Next app on Vercel with the Node runtime for backend auth, signup rate limits, hotkey, and database routes. Do not move these API routes to an edge runtime because they use server-only env validation, Better Auth, Neon, database-backed rate limits, and Substrate signature utilities.

Keep local, preview, and production URLs separate. Every URL used by Better Auth, app URLs, and trusted origins must match the environment that receives traffic.

EnvironmentURL checklist
LocalAPP_URL and BETTER_AUTH_URL use http://localhost:3000. BETTER_AUTH_TRUSTED_ORIGINS includes http://localhost:3000.
PreviewAPP_URL and BETTER_AUTH_URL use the active Vercel preview URL. Add that preview origin to BETTER_AUTH_TRUSTED_ORIGINS before testing signup.
ProductionAPP_URL and BETTER_AUTH_URL use https://platform.network. BETTER_AUTH_TRUSTED_ORIGINS includes https://platform.network and any canonical www alias that can start auth.

Required environment variables

Vercel project settings must define the same names as .env.example. Use placeholders in docs and examples only, never committed real values.

GroupVariables
App and Better AuthAPP_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, BETTER_AUTH_TRUSTED_ORIGINS
Neon and DrizzleDATABASE_URL
Signup rate limitsRATE_LIMIT_WINDOW_SECONDS, RATE_LIMIT_MAX_REQUESTS, AUTH_RATE_LIMIT_MAX_REQUESTS; signup registration is additionally fixed at 10 attempts per IP per hour in the database-backed rate limit table
Hotkey proofHOTKEY_NONCE_TTL_SECONDS, HOTKEY_SIGNATURE_NETWORK

Better Auth username signup

Generate a fresh BETTER_AUTH_SECRET for each real environment and store it only in the Vercel secret UI or local ignored env files. BETTER_AUTH_URL should be the exact public origin for that environment.

Signup uses username and password from the browser. The server checks the signup IP rate limit, validates the shared username policy, then forwards name, username, displayUsername, and an internal non-contact .invalid compatibility email to Better Auth.

SurfaceRequirement
POST /api/auth/sign-up/emailBrowser sends username and password. The server enforces 10 attempts per IP per hour and injects the Better Auth compatibility email.
Username policyLowercase 3 to 32 characters, letters and numbers, optional single internal hyphen or underscore, and reserved names rejected.
Dashboard accessRequires a signed-in credential account with a username. Contact email is not part of access.

Neon database and Drizzle migrations

Create a Neon Postgres database for each environment and set DATABASE_URL with sslmode=require. Use least-privilege credentials for deployed apps when Neon roles are available.

Generate migrations from schema changes before deployment, check them locally, then run migrations against the target Neon database from a controlled shell with that environment's DATABASE_URL loaded.

bash
npm run db:generate
npm run db:check
npm run db:migrate

Signup rate limit

Username registration does not use reCAPTCHA. The backend rate-limits POST /api/auth/sign-up/email to 10 attempts per IP per hour before reading the signup body.

The limit uses the shared database-backed rate_limits table and returns 429 with Retry-After and X-RateLimit headers when exhausted.

CheckServer behavior
First 10 attemptsAllowed within a one-hour IP window before username validation and Better Auth signup.
11th attemptReturns 429 RATE_LIMITED with retry metadata.
Missing IP headersFalls into the shared unknown-IP bucket instead of bypassing the limit.

Secret handling and deployment verification

Keep all real secrets out of git. Commit only placeholders in .env.example and docs. Review Vercel environment scopes before promoting preview values to production.

Before shipping, run the same checks locally and in CI where possible. Backend auth tests avoid live Upstash, Neon, and other external provider calls, but they still verify route gates and active auth controls.

bash
npm run typecheck
npm run build
npm run test:backend-auth
npm run test:browser-auth