coldstart

Deployment & infrastructure

Database, email, billing, and hosting setup

After scaffolding, you need to set up external services. You can do this manually, via coldstart setup, or conversationally with Claude Code and MCP servers.

Recommended order: Database first, then auth secrets, then billing, then email, then hosting. Each step depends on the previous one — billing needs auth, email needs a verified domain, and hosting needs all env vars set.

Interactive setup

Terminal
coldstart setup

Walks you through each service based on your project's .coldstart.json. Every step is optional and shows its status at the end.

Local development

Generated projects use portless for stable HTTPS *.localhost URLs during development:

Terminal
pnpm dev          # starts portless proxy + all apps
AppURL
Webhttps://web.<name>.localhost
APIhttps://api.<name>.localhost
MobileRuns natively on device/simulator (no portless)

Portless auto-starts on first pnpm dev run and provides valid HTTPS certificates for localhost.

If you prefer plain HTTP with classic ports, use PORTLESS=0 pnpm dev or pnpm dev:no-tls. Web runs on http://localhost:3000, API on http://localhost:3001.

Service by service

Database (Neon)

Claude Code
> Create a Neon database for my project

Claude uses the Neon MCP to create a project, gets the connection string, and writes it to apps/api/.env.

  1. Create a project at console.neon.tech
  2. Copy the connection string
  3. Add to apps/api/.env:
apps/api/.env
DATABASE_URL=postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require
  1. Run migrations:
Terminal
pnpm -F @my-app/db db:generate
pnpm -F @my-app/db db:migrate

Auth secrets

Generate a secret (min 32 characters) and configure the API URL:

apps/api/.env
BETTER_AUTH_SECRET=your-random-secret-at-least-32-characters
BETTER_AUTH_URL=https://api.my-app.localhost
CORS_ORIGIN=https://web.my-app.localhost

These URLs use portless (pnpm dev). If using plain HTTP (pnpm dev:no-tls), use http://localhost:3001 and http://localhost:3000 instead.

For OAuth providers, create apps on each provider's console and add the credentials.

Billing

  1. Create products and prices in Stripe Dashboard
  2. Configure webhook: Developers > Webhooks > Add endpoint
    • URL: https://your-api.com/webhooks/stripe
    • Events: customer.subscription.*, checkout.session.completed
  3. Add to apps/api/.env:
apps/api/.env
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
  1. Add to apps/web/.env:
apps/web/.env
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
  1. Create products on dashboard.polar.sh
  2. Configure webhook URL: https://your-api.com/webhooks/polar
  3. Add to apps/api/.env:
apps/api/.env
POLAR_ACCESS_TOKEN=...
POLAR_WEBHOOK_SECRET=...

For mobile billing, configure RevenueCat: create products matching your App Store/Play Store offerings, add API keys to your mobile .env.

Email (Resend)

Claude Code
> Set up Resend for my project

Claude uses the Resend MCP to configure a sending domain and add the API key.

  1. Create an account at resend.com
  2. Add and verify your domain
  3. Add API key to apps/api/.env:
apps/api/.env
RESEND_API_KEY=re_...

Email templates are in packages/email/src/ — preview them with pnpm -F @my-app/email preview (runs on port 3333).

Web hosting (Vercel)

Claude Code
> Deploy my web app to Vercel
Terminal
pnpm dlx vercel

Or connect your Git repo in the Vercel dashboard — auto-deploys on push.

API hosting (Docker)

The generated Dockerfile is a multi-stage build optimized for production:

Terminal
docker build -t my-api -f apps/api/Dockerfile .
docker run -p 3001:3001 my-api

Or use the docker-compose.yml for local development with PostgreSQL:

Terminal
docker compose up -d   # starts Postgres on port 5432

Mobile builds (EAS)

Terminal
cd apps/mobile
pnpm dlx eas-cli init --non-interactive

Then use the release scripts:

  • bash scripts/release-local.sh — full pipeline: version bump, EAS build, submit, TestFlight
  • bash scripts/release.sh — CI-friendly version bump

The Expo MCP server is configured for Claude Code to manage builds and submissions.

Environment checklist

Before going live, verify all required environment variables are set. Missing any will cause runtime errors.

Always required:

VariableDescription
DATABASE_URLNeon PostgreSQL connection string
BETTER_AUTH_SECRETRandom string, min 32 characters
BETTER_AUTH_URLPublic URL of your API (e.g. https://api.myapp.com)
CORS_ORIGINPublic URL of your web app (e.g. https://myapp.com)

If using email (Resend):

VariableDescription
RESEND_API_KEYResend API key (re_...)

If using OAuth:

VariableDescription
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETGoogle OAuth credentials
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETGitHub OAuth credentials
APPLE_CLIENT_ID / APPLE_CLIENT_SECRETApple OAuth credentials

If using Stripe:

VariableDescription
STRIPE_SECRET_KEYStripe secret key (sk_live_...)
STRIPE_WEBHOOK_SECRETStripe webhook signing secret (whsec_...)

If using Polar:

VariableDescription
POLAR_ACCESS_TOKENPolar API access token
POLAR_WEBHOOK_SECRETPolar webhook HMAC secret

If mobile billing:

VariableDescription
REVENUECAT_WEBHOOK_SECRETRevenueCat webhook Bearer token
VariableDescription
NEXT_PUBLIC_API_URLPublic URL of your API
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYStripe publishable key (if Stripe)
NEXT_PUBLIC_POSTHOG_KEYPostHog project API key
NEXT_PUBLIC_POSTHOG_HOSTPostHog host URL
VariableDescription
EXPO_PUBLIC_API_URLPublic URL of your API
EXPO_PUBLIC_REVENUECAT_API_KEYRevenueCat public API key (if billing)
EXPO_PUBLIC_POSTHOG_KEYPostHog project API key
EXPO_PUBLIC_POSTHOG_HOSTPostHog host URL

CI/CD

Two GitHub Actions workflows are generated:

WorkflowTriggerWhat it does
ci.ymlPush/PR to mainLint, check-types, test, build
deploy.ymlPush to mainVercel deployment placeholder
desktop.ymlVersion tagsTauri multi-platform builds (if desktop)
.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm lint
      - run: pnpm check-types
      - run: pnpm test
      - run: pnpm build

The deploy.yml workflow is a placeholder — connect your Vercel project via Git integration for automatic deployments, or customize the workflow with pnpm dlx vercel --prod --token $VERCEL_TOKEN.

Production checklist

Before launching, go through this checklist:

Switch to live API keys

Replace all test / sk_test_ / sandbox keys with production keys:

  • Stripe: sk_live_..., pk_live_..., new whsec_... for production webhook
  • Polar: production access token and webhook secret
  • RevenueCat: production API key (not sandbox)
  • Resend: production API key with verified domain

Update webhook URLs

Point all webhook endpoints to your production API:

  • Stripe: https://api.yourdomain.com/webhooks/stripe
  • Polar: https://api.yourdomain.com/webhooks/polar
  • RevenueCat: https://api.yourdomain.com/webhooks/revenuecat

Configure CORS and auth URLs

Update environment variables to use production domains:

apps/api/.env (production)
BETTER_AUTH_URL=https://api.yourdomain.com
CORS_ORIGIN=https://yourdomain.com

Set up custom domain on Vercel

Add your custom domain in the Vercel dashboard (Settings > Domains). Update NEXT_PUBLIC_API_URL in your web app's Vercel environment variables.

Verify monitoring

PostHog is already configured in generated projects. Verify that:

  • NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST are set in production
  • Events are flowing in app.posthog.com
  • Consider setting up error tracking alerts

Run the full build

Before your first production deployment, verify everything builds cleanly:

Terminal
pnpm lint && pnpm check-types && pnpm test && pnpm build

On this page