# YAML reference

Fields and complete examples for deliberate. Project configuration.

Canonical: https://docs.deliberate.space/reference/yaml/

Use this reference after the task-oriented [configuration
guide](/build/configuration/). Put resources below `.deliberate/`; `project.yaml`
selects the Team, Project, and Environment Flow, while every other document
starts with `resource:`.

## Project pin

```yaml
team: acme
project: chat
flow: default
```

## Resources

| Resource | Purpose |
| --- | --- |
| `component` | A long-running service, background worker, or scheduled job |
| `database` | Platform-operated PostgreSQL or FerretDB |
| `volume` | Durable, automatically expanding filesystem storage |
| `bucket` | Elastic S3-compatible object storage |
| `route` | Explicit public or Private Net HTTP routing |
| `domain` | A customer-owned hostname attached to an environment |
| `blueprint` | A pinned instance of a published Blueprint |
| `flow-pattern` | A custom persistent and disposable Environment topology |

## Components

Components declare an image and only the behavior they need. Ports are internal
unless they request `visibility: public` or `private`. No ports means a worker;
`schedule:` means a scheduled job.

```yaml
resource: component
name: app
image: ghcr.io/acme/app:1.4.2
cpu: 1
memory: 2Gi
ports:
  - port: 3000
    visibility: public
env:
  DATABASE_URL: "${{ postgres.url }}"
secrets:
  - SESSION_SECRET
needs:
  databases:
    - postgres
healthcheck:
  path: /health
```

Declaring `needs` authorizes the dependency; it injects nothing automatically.
Wire the output to the environment-variable name your software expects with a
`${{ name.output }}` expression.

## Complete example

This bundle describes a production application and its supporting resources.
Put it in `.deliberate/app.yaml`, next to `.deliberate/project.yaml`.

<!-- schema-example:start -->
```yaml
# PostgreSQL is addressed as `postgres` by the components below.
resource: database
name: postgres
engine: postgres
tier: prod
version: "17"
extensions:
  - vector

---
# Volumes grow automatically. `backup` selects the durability policy.
resource: volume
name: uploads
backup: offsite

---
# Buckets expose S3-compatible outputs such as endpoint and access_key.
resource: bucket
name: assets
expose: true
anonymousRead: false

---
resource: component
name: app
image: ghcr.io/acme/example-app:1.4.2
cpu: 1
memory: 2Gi
replicas: 1
class: standard
ports:
  - port: 3000
    protocol: http
env:
  NODE_ENV: production
  DATABASE_URL: "${{ postgres.url }}"
  DATABASE_POOL_URL: "${{ postgres.pooled_url }}"
  S3_ENDPOINT: "${{ assets.endpoint }}"
  S3_BUCKET: "${{ assets.bucket }}"
  S3_ACCESS_KEY: "${{ assets.access_key }}"
  S3_SECRET_KEY: "${{ assets.secret_key }}"
secrets:
  - SESSION_SECRET
needs:
  databases:
    - postgres
  buckets:
    - assets
  volumes:
    - name: uploads
      path: /app/uploads
healthcheck:
  path: /health
  port: 3000
  initialDelay: 15s
release:
  command: ["npm", "run", "migrate"]
  timeout: 10m
postDeploy:
  command: ["npm", "run", "warm-cache"]
  timeout: 5m
shutdown:
  gracePeriod: 60s
alerts:
  - name: elevated-error-rate
    type: http_error_rate
    threshold: 5
    window: 10m
    minRequests: 100
    recipients:
      - ops@example.com
overrides:
  preview-*:
    cpu: 0.125
    memory: 256Mi
    replicas: 1
    class: standard

---
# A worker is the same component primitive without a port.
resource: component
name: worker
image: ghcr.io/acme/example-app:1.4.2
command: ["npm", "run", "worker"]
cpu: 1
memory: 2Gi
env:
  DATABASE_URL: "${{ postgres.url }}"
needs:
  databases:
    - postgres

---
# Routes deliberately connect a hostname to a component.
resource: route
host: chat
visibility: public
rules:
  - path: /
    to: app
open:
  - label: Open Acme Chat
    path: /
    description: Open the customer-facing application.
  - label: Administration
    path: /admin
    description: Configure the application.
```
<!-- schema-example:end -->

The `needs` declarations grant the app access to the named resources. The
`${{ ... }}` expressions then map their outputs to the environment-variable
names this particular image expects. `release` runs before the new revision is
made current; `postDeploy` runs after deployment. Both use the bounded
[lifecycle hook contract](/build/lifecycle-hooks/). The `preview-*` override
keeps every matching preview environment smaller without changing production.

The route makes public exposure explicit. Change its visibility or replace its
host without changing the Component that serves it.

The parser rejects unknown fields.
