SsuperslateDocs
Build with the boilerplate

Deploy a fresh application

Execute the supported deployment path with readiness, smoke, rollback, and recovery evidence.

Deploy a fresh application

When to use

Use this path after a generated buyer application passes local verification and is ready for its first commercial deployment or a new isolated environment. It covers Railway, Dokploy, and the OpenTofu-managed AWS, GCP, and Azure backends with native, Vercel, or Cloudflare static frontends.

Read the deployment contract first. A host outside those targets is a new proof obligation, not a small variation of this runbook.

Files and boundaries

  • .node-version, .bun-version, root package.json: pinned toolchain.
  • apps/server/Dockerfile: standalone API artifact and runtime user.
  • apps/server/railway.toml: Railway build, readiness, and restart policy.
  • deploy/dokploy/compose.yml, deploy/dokploy/.env.example: reproducible self-hosted topology.
  • scripts/verify-dokploy-compose.sh: disposable production-container proof.
  • apps/server/.env.example, apps/server/src/config/env.ts: private runtime configuration.
  • apps/web/vercel.json, apps/web/.env.example: public static build configuration.
  • apps/web/wrangler.toml, apps/web/public/staticwebapp.config.json: static frontend adapters.
  • infra/: OpenTofu bootstrap, provider modules, executable roots, locks, and mocked tests.
  • deployment/config.json, deployment/README.md: locked non-secret selection and operator steps.
  • scripts/deploy/: migration-gated cloud release and native frontend scripts.
  • apps/server/src/main.ts: startup order.
  • apps/server/src/app.ts: liveness and readiness endpoints.
  • apps/server/migrations/: dbmate schema authority.
  • apps/server/email-templates/: rendered runtime templates.
  • .github/workflows/ci.yml: fresh-install, migration, buyer, build, and compiled-server proof.

The selected backend owns server secrets, Postgres, proxy behavior, and the API artifact. The selected frontend owns only the static browser build and its public VITE_* values. Provider dashboards own credentials, callback URLs, products, webhooks, and sender/domain verification.

Procedure

  1. Generate the buyer repository and install from its own frozen lockfile.

  2. Honor .node-version and .bun-version; confirm the root pnpm version from packageManager.

  3. Start disposable Postgres and run:

    vp install --frozen-lockfile
    vp check
    pnpm test
    vp run -r build
    docker build --pull -f apps/server/Dockerfile -t app-server:release .
    bash scripts/verify-dokploy-compose.sh
  4. Prove migration reversibility on a disposable database with up → down → up. Do not use an ambient or production DATABASE_URL.

  5. Choose exactly one supported API target. Railway uses apps/server/railway.toml; Dokploy uses deploy/dokploy/compose.yml. For AWS, GCP, or Azure, run pnpm deploy:configure if deployment was deferred during application creation, review the generated checklist, bootstrap isolated state, select native S3/GCS or R2 storage, and dispatch the protected OIDC workflow. Azure uses R2 because Azure Blob storage is not included.

  6. Set DATABASE_URL, a new 32+ character BETTER_AUTH_SECRET, LOG_PRETTY=false, the exact TRUSTED_PROXY_PROFILE, exact HTTPS FRONTEND_URL and SERVER_URL, pool limits, deployment metadata, a verified EMAIL_FROM, and RESEND_API_KEY in the selected API platform.

  7. Leave MIGRATIONS_DIR and EMAIL_TEMPLATES_DIR unset for the included image. Configure optional Google, the selected billing provider, and storage integrations atomically or leave each complete integration unset.

  8. Run ./server migrate as a one-shot release step using the exact image digest. Deploy the API only after it exits zero, then require /ready to return 200. Confirm all 9/9 templates are preloaded and the structured release metadata matches the digest.

  9. Deploy the chosen static frontend with VITE_APP_ENV=production and exact HTTPS VITE_API_URL. For Vercel or Cloudflare, use the stable production origin supplied before the backend apply.

  10. Register the exact Google callback and selected-provider webhook routes when those integrations are enabled.

  11. Deploy the web artifact and execute the new-browser production smoke checklist in docs/deployment.md.

  12. Record artifact IDs, command results, URL, measured cost, interventions, architecture violations, and smoke evidence in the agent evaluation harness.

Verification

Before any external deploy:

vp check
pnpm test
vp run -r build
bun test --cwd packages/create-app src/deployment-contract.test.ts
docker build --pull -f apps/server/Dockerfile -t app-server:release .

For the container proof, run the image as its non-root user against disposable Postgres and require:

GET /health -> 200 {"status":"ok",...}
GET /ready  -> 200 {"status":"ready",...}

Inspect the running container uid/gid, its Docker health state, the startup migration result, and the 9/9 template preload. Then execute the auth and enabled-integration smoke checks; a green health endpoint alone is not deployment proof.

Security constraints

  • Generate new secrets per environment and enter them only in the owning provider.
  • Treat every VITE_* value as public. Never expose server keys, secrets, connection strings, or private URLs through the web build.
  • Use exact HTTPS origins and callback URLs. Do not use wildcard credentialed CORS.
  • Select the exact supported proxy profile and keep the origin inaccessible around its ingress.
  • Schedule and test an application-database backup. A Dokploy control-plane backup is separate.
  • Use sandbox/test provider products for proof; do not create a real billable test purchase.
  • Use a new browser profile and non-customer test identity for production smoke checks.
  • Redact tokens, cookies, private connection details, and email links from evaluation and Linear evidence.

Failure modes

  • Building the server with apps/server as Docker context, which omits the workspace lockfile.
  • Leaving VITE_APP_ENV unset, causing production instrumentation and behavior to be classified as development.
  • Pointing VITE_API_URL, FRONTEND_URL, SERVER_URL, CORS, OAuth, and webhook configuration at different origins.
  • Marking the service healthy from /health while Postgres, migrations, or templates are unusable.
  • Allocating replica pool limits that leave less than 20% of database connections for release and administrative work.
  • Partially configuring the selected billing provider, Google, storage, or Resend.
  • Rolling back application code after an incompatible or destructive schema change.
  • Treating a local Docker proof as evidence that external email, auth cookies, callbacks, billing, storage, DNS, and TLS work.

Rollback and diagnosis

If the API does not become ready, preserve logs and identify whether environment validation, database connectivity, migration execution, or resource preload failed. Keep the new artifact out of service and redeploy the previous schema-compatible artifact. Use the failed-migration golden path before any down, manual SQL, or version-table change.

If the web build fails, inspect the frozen install, exact Vite environment, and output directory. If the deployed SPA regresses, restore the previous static artifact together with the API version whose contract it expects.

Rotate credentials after any accidental bundle, log, transcript, or issue exposure. A corrected deploy does not make an exposed secret safe again.

Acceptance criteria

  • A clean generated buyer repository passes frozen install, checks, tests, builds, migrations, and the exact Docker build.
  • The API runs as non-root, preloads required resources before traffic, and reports database-backed readiness.
  • Frontend and selected backend environment ownership is explicit and contains no misplaced secret.
  • Password, verification, magic link, reset, session, email, CORS, and every enabled optional integration pass the deployed smoke checklist.
  • Release and rollback order are compatible with the schema.
  • Measured recurring cost and excluded overages are recorded.
  • The evaluation record contains no credentials or customer data.

Agent prohibitions

  • Do not create provider projects, domains, products, or permanent account names without the founder's approval.
  • Do not claim a deployed integration from config, mocks, a local container, or a health response.
  • Do not change the selected supported topology to avoid diagnosing its failure.
  • Do not route Railway or Dokploy readiness to /health.
  • Do not add replicas, a worker, a queue, or another cloud/provider during first-deploy proof.
  • Do not put secrets in Git, Docker layers, VITE_*, browser logs, evaluation evidence, or Linear.
  • Do not apply, reverse, or repair migrations against an unconfirmed database target.

On this page