DeploymentHosted PaaS Deploys

Hosted PaaS Deploys

Deploy your SiteKnock app to Vercel, Cloudflare Workers, Railway, or Netlify directly from Studio — without building Docker containers.

Beyond containers

The default SiteKnock deploy model builds two Docker containers (Next.js frontend + Express backend). If you prefer a hosted platform, Studio can deploy directly to several PaaS providers instead — no container builds, no Docker daemon required.

Studio treats each of these as a Hosted PaaS target. The platform runs your code on its own infrastructure; Studio handles credential resolution, resource provisioning, environment variables, and the deploy command.

Supported platforms

PlatformWhat Studio deploysService modeCLI required
VercelFrontend (Next.js) + backend (Hono Functions)Split, frontend and/or backend enabledNo (uses Vercel API)
Cloudflare WorkersFrontend (Next.js via OpenNext) + backend (Hono Worker)Split, frontend and/or backend enabledNo (uses wrangler via pnpm)
ConvexBackend only (Convex functions)Split, backend enabled, frontend disabledNo (uses convex CLI via pnpm)
RailwayFrontend and/or backendSplit or monolithYes (@railway/cli)
NetlifyFrontend (Next.js) + backend (Hono Functions)Split, frontend and/or backend enabledYes (netlify-cli)

Vercel, Cloudflare Workers, and Netlify can now host both frontend and backend — but only when the backend framework is Hono. Express backends require a long-lived Node.js process and are container-only; deploy them to Docker, Railway, or convert to Hono first. Convex is the inverse: backend-only, hosting serverless functions instead of the frontend. See Backend Frameworks for the Express vs Hono comparison and how to switch.

Connecting your account

Each platform uses a shared integration connection stored in Studio:

  1. Open Settings → Integrations in Studio.
  2. Add a connection for your provider (Vercel token, Cloudflare API token, Convex access token, Railway API token, or Netlify personal access token).
  3. Save the connection. Studio validates the credential against the provider's API.

See Integrations & Remote for details on managing shared connections.

Setting up a PaaS target

  1. Add a target in the deployment workspace and choose your platform as the orchestrator. The target class is automatically set to Hosted PaaS.
  2. Select your connection from the shared connection picker.
  3. Load resources — Studio fetches your projects, sites, teams, or workers from the provider API.
  4. Choose a resource (project, site, worker, team) or leave it blank to let Studio auto-create one on first deploy.
  5. Configure the environment — set the service mode and environment variables for the target.

Environment variables

Studio pushes environment variables from the deployment workspace to the provider at deploy time. Variables scoped to shared or the matching service ID are included.

For Vercel and Cloudflare Workers, Studio also injects a generated .env.production or wrangler.jsonc with the configured values so the build picks them up.

What Studio does not manage

All hosted PaaS targets share these limitations — the provider manages runtime, not Studio:

  • Runtime lifecycle — start, stop, restart, and remove are handled by the platform.
  • Logs — use the provider's dashboard for real-time logs.
  • Plan previews — Docker Compose plan previews are not available for hosted PaaS targets.
  • Docker-specific config — port mappings, volumes, labels, secrets, and configs don't apply.

Vercel

Vercel deploys can ship both frontend and Hono backend. The frontend is a Next.js app; the Hono backend runs as Vercel Functions via the hono/vercel adapter (an api/[[...route]].ts catch-all). Studio stages a snapshot from your app root, rewrites @siteknock/* workspace dependencies to published versions, runs corepack pnpm install and the build on Vercel's infrastructure, and injects a .env.production file from your deployment workspace env rows.

Requirements

  • Environment must be split mode.
  • Frontend: enabled, deploys as a Next.js app.
  • Backend: enabled only if backendFramework is Hono. Express backends are rejected — Studio throws a clear error pointing you to siteknock app convert-framework --to hono.
  • A Vercel project is auto-created if you don't choose one. Studio sets the root directory and framework automatically.

What gets staged

Studio stages only what the Vercel build needs: package.json, pnpm-workspace.yaml, .npmrc, tsconfig.json, turbo.json, design_guidelines.json, config/, locales/, pages/, and apps/<app>-fe/. When the Hono backend is enabled, the backend source directory is also staged. E2e, emails, scripts, and Dockerfiles are excluded.

Cloudflare Workers

Cloudflare Workers deploys can ship both frontend and Hono backend as two separate Workers. The frontend uses OpenNext to adapt your Next.js app for the Workers runtime. The Hono backend runs as its own Worker with a nodejs_compat flag, deployed via wrangler deploy.

Requirements

  • Environment must be split mode.
  • Frontend: enabled, deploys as a Next.js app via OpenNext.
  • Backend: enabled only if backendFramework is Hono. Express backends are rejected — Studio throws a clear error pointing you to siteknock app convert-framework --to hono, disable the backend service, or move it to a Docker target.
  • A Cloudflare Worker is auto-created if you don't choose one. The backend Worker is named <worker-name>-api.
  • The Cloudflare connection needs both an API token and an account ID.

What happens during deploy

Frontend Worker:

  1. Studio stages a build context from your app source.
  2. Generates wrangler.jsonc with your worker name, compatibility date, and env vars.
  3. Generates open-next.config.ts for the OpenNext adapter.
  4. Runs pnpm install, installs @opennextjs/cloudflare and wrangler, runs sk:generate.
  5. Builds the Next.js app and runs opennextjs-cloudflare deploy.

Backend Worker (Hono only):

  1. Studio writes a src/worker.ts shim in the backend directory that lazy-initialises the Hono app on first request and injects the D1 binding (env.DB) into the Prisma D1 adapter via globalThis.__SK_D1_BINDING__.
  2. Generates a separate wrangler.jsonc for the backend Worker with nodejs_compat flag, env vars, routes, and custom domains.
  3. Installs wrangler in the backend directory.
  4. Runs wrangler deploy with the backend wrangler config.

Cloudflare Ingress (routes & custom domains)

By default, a deployed Worker is reachable at <worker-name>.workers.dev. For production, you'll want to route traffic through your own domain. Studio's deployment workspace provides a Cloudflare Ingress configuration for both the frontend and backend Workers:

  • Worker routes — zone-based patterns (e.g., example.com/*, app.example.com/*) that match incoming requests and route them to the Worker. The zone must live on the same Cloudflare account as the API token.
  • Custom domains — hostnames that Cloudflare provisions with DNS records, allowing the Worker to be accessed at custom domain names (e.g., app.example.com, api.example.com).

When custom ingress (routes or custom domains) is configured, Studio automatically disables the default workers.dev URL — the custom domain becomes the canonical URL. When no custom ingress is set, workers.dev is enabled so the Worker is reachable out of the box.

To configure ingress in the deployment workspace:

  1. Select your Cloudflare target or build.
  2. Click the Cloudflare Ingress button to open the configuration modal.
  3. Enter routes (one per line) — zone-based patterns like example.com/*.
  4. Enter custom domains (one per line) — hostnames like app.example.com.
  5. Save. Studio writes the values to the target's providerMetadata and includes them in the generated wrangler.jsonc at deploy time.

Backend ingress (routes and custom domains for the -api Worker) is only shown when the backend framework is Hono and the backend service is enabled.

Railway

Railway deploys can ship both frontend and backend (or a monolith). Studio uses the Railway CLI (railway up) to deploy each service's source directory to a Railway service, auto-creating the project, environment, and service if they don't exist.

Requirements

  • The Railway CLI must be installed: npm install -g @railway/cli.
  • An environment is auto-selected (typically the first one, usually "production").
  • Studio creates a Railway service for each enabled service, named after the service ID. For a single-app project with default folder names, that's frontend and backend (or app in monolith mode). For a multi-app project, the service names match the app folder names — e.g. my-app-fe and my-app-be.

What happens during deploy

  1. Studio resolves or creates the Railway project and environment.
  2. For each enabled service, Studio ensures a Railway service exists and sets environment variables via the GraphQL API.
  3. Runs railway up --detach --json to push the source and trigger a build.
  4. Polls the deployment status until it succeeds or fails.

Netlify

Netlify deploys can ship both frontend and Hono backend. The frontend is a Next.js app; the Hono backend runs as Netlify Functions via the hono/netlify adapter (a netlify/functions/[[route]].ts catch-all). Studio uses the Netlify CLI (netlify deploy) to deploy, auto-creating the site if it doesn't exist.

Netlify can host Express apps via Netlify Functions

  • serverless-http, but SiteKnock's Express backend uses long-lived processes (Prisma connection pooling, Redis cache, rate limiter state) that don't fit the serverless function model. Studio therefore restricts Netlify backend deploys to Hono only. If you need a PaaS backend with Express, use Railway or Convex instead, or convert to Hono with siteknock app convert-framework --to hono.

Requirements

  • Environment must be split mode.
  • Frontend: enabled, deploys as a Next.js app.
  • Backend: enabled only if backendFramework is Hono. Express backends are rejected — Studio throws a clear error pointing you to siteknock app convert-framework --to hono.
  • The Netlify CLI must be installed: npm install -g netlify-cli.
  • A Netlify site is auto-created if you don't choose one.
  • Studio deploys with --prod --no-build — it uploads the service directory as-is. Make sure your build output is ready, or configure Netlify's build settings.

What happens during deploy

  1. Studio resolves or creates the Netlify site.
  2. Sets environment variables on the site via the REST API.
  3. Runs netlify deploy --dir <source> --site <id> --prod --no-build.
  4. Polls the deployment status until it's ready or errors.

Build overrides

All hosted PaaS targets support build-level overrides. Set paasSettingsMode to override on an image build to configure platform-specific settings (project name, site name, team, environment, etc.) at the build level instead of the target level. This lets you deploy the same app to different provider resources from different environments.

One backend, multiple PaaS frontends

A common pattern is to deploy the same backend once (e.g. on Railway or as a Hono Worker on Cloudflare) and point multiple PaaS frontends at it (a Railway frontend, a Vercel frontend, a Netlify frontend, a Cloudflare frontend). This lets you compare platforms side-by-side or run canary deploys without provisioning a second backend.

For this to work, the backend must allow CORS and auth from every frontend origin — not just one. Set these env vars on the backend service:

VariableExamplePurpose
AUTH_ALLOWED_HOSTS*.siteknock.comComma-separated allowed frontend hostnames — each entry can be an explicit hostname or a wildcard pattern (e.g. *.siteknock.com,app.example.com). Drives both CORS and Better Auth's dynamic base URL.
AUTH_COOKIE_DOMAIN.siteknock.comParent domain for the session cookie so it's shared across all subdomain frontends.

With a wildcard like *.siteknock.com, any new *.siteknock.com PaaS frontend you deploy will work against the same backend without editing env vars. The wildcard matches Better Auth's semantics: * crosses dots but not slashes, so demo-netlify.siteknock.com and a.b.siteknock.com are allowed, but evil.siteknock.com.attacker.com is not (it doesn't end with .siteknock.com).

See Multi-frontend auth and CORS in the Deployment Overview for the full details.

Next steps