.preview.yaml Reference

The .preview.yaml file at the root of your repository tells Previewkit how to build and deploy your stack for each pull request. This page documents every field.

Top-level shape

version: 1 # required, must be 1
domain: string? # optional, override preview hostname suffix
registry: string? # optional, override image registry
apps: [App] # required, at least one
services: [Service] # optional
hooks:
post_deploy: [Hook] # optional
FieldTypeDefaultNotes
version1requiredSchema version. Only 1 is supported today.
domainstringpreview.autonoma.appOverrides the hostname suffix. Wildcard DNS must be configured by the operator.
registrystringplatform defaultContainer registry to push built images to. Usually leave unset.
appslistrequiredOne or more applications. Each gets a public HTTPS URL.
serviceslist[]Backing services from the recipe catalog (databases, caches, etc.).
hooksobject{}Lifecycle hooks. Today only post_deploy is supported.

Apps

Each entry under apps becomes a Kubernetes Deployment plus a public HTTPS hostname.

apps:
- name: api
path: ./apps/api
dockerfile: ./apps/api/Dockerfile # optional
build_args: # optional
NODE_VERSION: "20"
port: 4000
env:
DATABASE_URL: "postgresql://preview:preview@{{db.host}}:5432/preview"
command: "node dist/server.js" # optional, overrides image CMD
health_check: /health # optional
replicas: 1
resources:
cpu: 500m
memory: 512Mi
FieldTypeDefaultNotes
namestringrequiredKubernetes-style name (lowercase letters, digits, hyphens). Also the leftmost label of the hostname.
pathstring"."Path to the build context, relative to the repo root.
dockerfilestringautodetectPath to a Dockerfile (relative to repo root). If omitted, Previewkit looks for Dockerfile inside path; if none is found, Railpack auto-detects the framework.
build_argsmap<string, string>{}Build-time --build-arg values.
portintegerrequiredThe container port the app listens on.
envmap<string, string>{}Runtime environment variables. Supports templating.
commandstringimage CMDOptional shell command to override the image entrypoint. Wrapped in /bin/sh -c.
health_checkstringnoneHTTP path for both readiness and liveness probes.
replicasinteger1Number of pod replicas.
resources.cpustring"250m"CPU request (no limit).
resources.memorystring"256Mi"Memory request and limit.

Resulting URL

For an app named web in PR #42 of acme-corp/storefront, the URL is:

https://web-pr-42-acme-corp-storefront.preview.autonoma.app

(Repo slugs are sanitized to fit DNS-label limits — long owner/repo names are truncated.)

Services

Services come from a curated recipe catalog. You don’t write Kubernetes manifests — you pick a recipe and Previewkit handles everything (Deployment, Service, persistent volume, readiness probes).

services:
- name: db
recipe: postgres
version: "16"
env:
POSTGRES_DB: app
resources:
cpu: 500m
memory: 1Gi
FieldTypeDefaultNotes
namestringrequiredUsed by other apps to address this service ({{<name>.host}}).
recipestringrequiredOne of the recipes listed below.
versionstringrecipe defaultImage tag for the underlying service.
envmap<string, string>{}Extra environment variables for the service container.
optionsmap{}Recipe-specific config. See each recipe below.
resourcesobject250m / 256MiSame shape as app resources.

Available recipes

RecipeDefault versionPortNotes
postgres16-alpine5432Persistent volume attached. Connection: postgresql://preview:preview@{{name.host}}:5432/preview.
redis7-alpine6379No persistence. Connection: redis://{{name.host}}:6379.
valkey7-alpine6379Open-source Redis fork. Same connection shape.
temporal(recipe-default)7233Local Temporal cluster for workflow testing.
api-gateway1.27-alpine80Nginx-based router that fans requests to multiple apps. Requires options.routes.

api-gateway options

services:
- name: gateway
recipe: api-gateway
options:
client_max_body_size: 25m
routes:
- path: /api
target: api
strip_prefix: true
- path: /
target: web

Each route has path (URL prefix to match), target (app or service name to forward to), strip_prefix (boolean), and rewrite (optional path rewrite).

Hooks

hooks:
post_deploy:
- app: api
command: "npx prisma migrate deploy"
- app: api
command: "node scripts/seed.js"

post_deploy runs after every app is deployed and at least one pod for the target app is Running. Each step is executed via the Kubernetes API exec subresource (no kubectl needed), wrapped in /bin/sh -c. Steps run sequentially; the first failure aborts the rest.

FieldTypeNotes
appstringName of an app declared in apps. The hook runs inside its pod.
commandstringShell command to execute.

Environment templating

The env map on apps (and on services) supports two kinds of placeholders that resolve at deploy time:

Service references

{{<name>.host}} and {{<name>.port}} resolve to the in-namespace DNS name and port of another app or service.

apps:
- name: web
env:
API_URL: "http://{{api.host}}:{{api.port}}"
- name: api
env:
DATABASE_URL: "postgresql://preview:preview@{{db.host}}:5432/preview"
REDIS_URL: "redis://{{cache.host}}:{{cache.port}}"
services:
- name: db
recipe: postgres
- name: cache
recipe: redis

{{name.host}} is always the bare service name (in-cluster DNS). {{name.port}} is the recipe’s known port for services, or the declared port for apps.

Unknown names raise a deploy error with the list of valid names.

Context variables

Three variables describe the current PR context:

VariableValue
{{pr}}PR number (e.g. 42)
{{namespace}}Kubernetes namespace (preview-<owner>-<repo>-pr-<N>)
{{owner}}Repo owner (e.g. acme-corp)
apps:
- name: api
env:
ENV_LABEL: "pr-{{pr}}-{{owner}}"
S3_PREFIX: "previews/{{namespace}}/"

Full example

version: 1
apps:
- name: web
path: ./apps/web
port: 3000
env:
API_URL: "http://{{api.host}}:{{api.port}}"
DATABASE_URL: "postgresql://preview:preview@{{db.host}}:5432/preview"
health_check: /health
- name: api
path: ./apps/api
dockerfile: ./apps/api/Dockerfile
port: 4000
env:
DATABASE_URL: "postgresql://preview:preview@{{db.host}}:5432/preview"
REDIS_URL: "redis://{{cache.host}}:6379"
ENV_LABEL: "pr-{{pr}}"
health_check: /health
resources:
cpu: 500m
memory: 512Mi
services:
- name: db
recipe: postgres
version: "16"
- name: cache
recipe: redis
hooks:
post_deploy:
- app: api
command: "npx prisma migrate deploy"

Validation tips

  • Names must match ^[a-z0-9][a-z0-9-]*[a-z0-9]$ (Kubernetes-compatible).
  • At least one app is required.
  • version must be exactly 1.
  • Service references in env must match a name declared elsewhere in the same file.
  • Hostnames combine <app>-pr-<N>-<repo-slug> and must stay under 63 characters — keep app names short.
Link copied