Deployment

Capstan applications compile to portable bundles that run on Node.js, Docker, serverless platforms, and edge runtimes.

Build Command

npx capstan build

The build command compiles your TypeScript source into JavaScript ready for production. It runs tsc to compile all files in app/ and capstan.config.ts. Output goes to the dist/ directory as ESM with .js extensions.

Build Output

After a successful build, Capstan writes a deterministic deployment contract to dist/:

FilePurpose
dist/_capstan_server.jsProduction server entrypoint used by capstan start
dist/_capstan_manifest.jsonCompiled route manifest
dist/agent-manifest.jsonAgent manifest projection
dist/openapi.jsonOpenAPI projection
dist/deploy-manifest.jsonMachine-readable deployment contract for tooling and CI
dist/public/Static assets copied from app/public/
dist/static/Pre-rendered SSG output when using capstan build --static
dist/standalone/Self-contained deployment directory when using an explicit deployment target

Build Targets

Capstan supports six build targets. Pass the target name to --target:

npx capstan build --target node-standalone
npx capstan build --target docker
npx capstan build --target vercel-node
npx capstan build --target vercel-edge
npx capstan build --target cloudflare
npx capstan build --target fly
TargetExtra FilesDeploy Command
node-standaloneRuntime-only package.jsoncd dist/standalone && npm start
dockerDockerfile, .dockerignoredocker build dist/standalone
vercel-nodeapi/index.js, vercel.jsoncd dist/standalone && vercel deploy
vercel-edgeapi/index.js, vercel.json, runtime/*.jscd dist/standalone && vercel deploy
cloudflareworker.js, wrangler.toml, runtime/*.jscd dist/standalone && wrangler deploy
flyDockerfile, .dockerignore, fly.tomlcd dist/standalone && fly deploy
Note: Edge and worker targets (vercel-edge, cloudflare) generate a portable runtime bundle under runtime/ that does not rely on runtime filesystem reads. The bundle embeds the route manifest, compiled modules, and static assets.

Production Server

npx capstan start

The start command:

  1. Loads the compiled capstan.config.ts from dist/
  2. Reads the pre-built route manifest from dist/_capstan_manifest.json
  3. Starts a Hono HTTP server on the configured port
  4. Mounts all API handlers, page renderers, and agent protocol endpoints
  5. Serves static files from dist/public/

To start from a standalone output:

npx capstan start --from dist/standalone
npx capstan start --port 8080

Or configure in capstan.config.ts:

export default defineConfig({
  server: {
    port: 8080,
    host: "0.0.0.0",
  },
});

Static Site Generation

npx capstan build --static

This crawls all page routes at build time, renders them to HTML, and outputs static files in dist/static/. Serve them from any CDN or static host.

Environment Variables

Capstan reads environment variables using the env() helper:

import { env } from "@zauso-ai/capstan-core";

const dbUrl = env("DATABASE_URL");  // Returns "" if not set
VariableDescriptionExample
DATABASE_URLDatabase connection stringpostgres://user:pass@host:5432/db
SESSION_SECRETHMAC signing secret for JWT sessionsyour-secret-key-here
PORTPlatform-provided server port3000
CAPSTAN_PORTOverride port for capstan start3000
CAPSTAN_HOSTServer bind address0.0.0.0
CAPSTAN_CORS_ORIGINExplicit allowed origin for CORShttps://app.example.com
CAPSTAN_MAX_BODY_SIZEMax request body size in bytes1048576
NODE_ENVEnvironment (production/development)production
Important: Never commit .env files to version control. The scaffolder generates a .gitignore that excludes .env and .env.local.

Docker Deployment

The docker target generates a multi-stage Dockerfile:

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
COPY . .
RUN npx capstan build --target node-standalone

FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist/standalone/package.json ./package.json
RUN npm install --omit=dev
COPY --from=builder /app/dist/standalone/dist ./dist
EXPOSE 3000
ENV NODE_ENV=production
ENV PORT=3000
ENV CAPSTAN_HOST=0.0.0.0
CMD ["node", "dist/_capstan_server.js"]

Running with Docker Compose:

# Build and start
docker compose up -d

# Run migrations
docker compose exec app npx capstan db:push

# View logs
docker compose logs -f app

Vercel

Capstan provides both Node.js and Edge deployment targets for Vercel:

# Node.js serverless
npx capstan build --target vercel-node
npx capstan verify --deployment --target vercel-node
cd dist/standalone && vercel deploy

# Edge runtime
npx capstan build --target vercel-edge
npx capstan verify --deployment --target vercel-edge
cd dist/standalone && vercel deploy

Use vercel-node for apps with Node runtime dependencies or session auth. Use vercel-edge when the app is edge-safe and you want the portable runtime bundle.

Cloudflare Workers

npx capstan build --target cloudflare
npx capstan verify --deployment --target cloudflare
cd dist/standalone && wrangler deploy

Fly.io

npx capstan build --target fly
npx capstan verify --deployment --target fly
cd dist/standalone && fly deploy

deploy:init

To generate project-root deployment assets instead of deploying from dist/standalone/:

npx capstan deploy:init --target docker
TargetGenerated Files
dockerDockerfile, .dockerignore, .env.example
vercel-nodevercel.json, .env.example
vercel-edgevercel.json, .env.example
cloudflarewrangler.toml, .env.example
flyDockerfile, .dockerignore, fly.toml, .env.example

Deployment Verification

Run deployment verification after building a target:

npx capstan verify --deployment --target vercel-edge
npx capstan verify --deployment --target cloudflare --json

Verification checks:

  • Target-specific files (vercel.json, wrangler.toml, fly.toml, entrypoints)
  • Portable runtime bundle files for edge and worker targets
  • Unsafe SQLite usage on serverless, edge, or multi-region targets
  • Auth/runtime mismatches for edge deployments
  • node: imports that would break edge or worker runtimes

Agent Discovery in Production

In production, agent endpoints are served from the build output. Ensure your reverse proxy or CDN does not strip the /.well-known/ path:

# Verify agent discovery is working
curl https://your-app.example.com/.well-known/capstan.json

Production Checklist

  1. Set SESSION_SECRET to a strong, unique value
  2. Set DATABASE_URL to your production database
  3. Set NODE_ENV=production
  4. Run capstan verify and capstan verify --deployment --target <target>
  5. Run capstan build --target <target> and verify the deployment bundle
  6. Run migrations with capstan db:push or capstan db:migrate
  7. Enable HTTPS via a reverse proxy (nginx, Caddy, or cloud load balancer)
  8. Review policies to ensure write endpoints require authentication
SQLite in production: If using SQLite (single-server), use a persistent volume for the database file. WAL mode is enabled by default. Consider PostgreSQL for multi-instance deployments.