Stack JSON Reference
The stack.json file is the core of every Swisblade project. It defines your services, their dependencies, and how they connect. Place it at the root of your repository.
Format
{
"name": "my-project",
"services": {
"service-name": {
"type": "app",
"source": { "repo": "github.com/you/repo.git", "ref": "main" },
"runtime": "node",
"port": 3000,
"public": true,
"needs": ["postgres", "redis"],
"connects_to": ["worker"],
"requires_env": ["API_KEY", "STRIPE_SECRET"]
}
}
}
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name. Used for display and slug generation. |
version | number | No | Schema version (for future use). |
services | object | Yes | Map of service name → service definition. |
Service definition
Each key in services is a service name (used for DNS, env var names, and logging). Service names should be lowercase alphanumeric with hyphens.
Common fields
| Field | Type | Default | Description |
|---|---|---|---|
type | string | — | "app", "custom", or "database". Required. |
port | number | — | Internal port the service listens on. |
connects_to | string[] | [] | Other services this one communicates with. |
requires_env | string[] | [] | Env vars that must exist in the vault before deploying. Optional. |
App services (type: "app")
Application services are built from your source code.
| Field | Type | Required | Description |
|---|---|---|---|
source | object | Yes | { repo, ref } for git repos, or { path } for local/monorepo. |
source.repo | string | — | Git repository URL (e.g., github.com/you/api.git). Required for git source. |
source.ref | string | — | Branch, tag, or commit SHA to deploy. Required for git source. |
source.path | string | — | Relative path to the service directory. Required for local source. |
runtime | string | Yes | "node", "python", or "java". Used for auto-instrumentation. |
port | number | Yes | Port your application listens on inside the container. |
public | boolean | No | Expose this service with a public HTTPS URL. |
needs | string[] | No | Shared infrastructure to provision. See needs. |
requires_env | string[] | No | Env var names the service requires. Validated against the vault before deploy. |
auth | object | No | Put a login in front of this service. See Authentication. |
custom_domain | string | No | Serve this service on your own domain, alongside the free URL. See Custom Domains. Requires public: true. |
image | string | No | Override: use this Docker image instead of building. |
Custom services (type: "custom")
Pre-built Docker images (e.g., RabbitMQ, Elasticsearch).
| Field | Type | Required | Description |
|---|---|---|---|
image | string | Yes | Docker image (e.g., rabbitmq:3-management). |
port | number | No | Internal port. |
protocol | string | No | Protocol for URL generation (default: "http"). |
version | string | No | Image version tag. |
Database services (type: "database")
Named database services run on the shared platform infrastructure with their own credentials. Use them when a service needs a separate database (e.g., an analytics DB distinct from the main one).
| Field | Type | Required | Description |
|---|---|---|---|
engine | string | Yes | "postgres" or "mysql". |
{
"analytics-db": {
"type": "database",
"engine": "mysql"
}
}
App services connect to database services via connects_to. The injected env var follows the pattern DATABASE_URL_{NAME}:
{
"worker": {
"type": "app",
"connects_to": ["analytics-db"]
}
}
This injects DATABASE_URL_ANALYTICS_DB=mysql://proj_xxx_analytics_db:password@platform-mysql:3306/proj_xxx_analytics_db.
Each named database gets its own user and schema, isolated from the default database provisioned by needs.
Named databases count toward your plan's database limit. The free tier allows 2 databases per stack (including the default one from needs).
needs
The needs array declares shared infrastructure that Swisblade provisions and manages for you. Connection credentials are injected automatically.
"needs": ["postgres", "redis", "rabbitmq"]
| Value | What you get | Env var injected |
|---|---|---|
"postgres" | PostgreSQL 16 database with dedicated user | DATABASE_URL |
"mysql" | MySQL 8 database with dedicated user | DATABASE_URL |
"redis" | Redis 7 with isolated key prefix | REDIS_URL + REDIS_KEY_PREFIX |
"rabbitmq" | RabbitMQ vhost with dedicated user | MQ_URL |
Each service gets its own credentials, isolated from other projects. You can also use the object form for custom naming:
"needs": [{ "type": "postgres", "name": "analytics-db" }]
connects_to
Declares service-to-service communication within the same project. Swisblade injects the target service's internal URL as an environment variable.
{
"api": {
"type": "app",
"connects_to": ["worker", "notifications"]
}
}
This injects:
WORKER_URL=http://worker:8080NOTIFICATIONS_URL=http://notifications:3000
The URLs use Docker's internal DNS — services can reach each other by name within the same project.
When connects_to points to a type: "database" service, a connection string is injected instead:
{
"api": { "type": "app", "connects_to": ["analytics-db"] },
"analytics-db": { "type": "database", "engine": "postgres" }
}
This injects DATABASE_URL_ANALYTICS_DB=postgresql://... with dedicated credentials.
requires_env
Optional pre-deploy validation. Lists environment variable names that must exist in the project vault before the deploy starts. If any are missing, the deploy fails immediately with a clear error.
"requires_env": ["STRIPE_KEY", "WEBHOOK_SECRET"]
All variables stored in the vault are automatically injected into every service at deploy time — you don't need to declare them in stack.json. The requires_env field is a safety net: it ensures critical variables are present before your containers start.
If you don't declare requires_env, the deploy proceeds without checking. If a variable is missing, your application will fail at runtime instead of at deploy time.
See Environment Variables for details on managing the vault.
Full example
A multi-service project with an API, worker, named database, cache, and message queue:
{
"name": "ecommerce",
"services": {
"api": {
"source": { "repo": "github.com/myorg/api.git", "ref": "v2.1.0" },
"type": "app",
"runtime": "java",
"port": 3000,
"public": true,
"needs": ["postgres", "redis"],
"connects_to": ["worker"],
"requires_env": ["STRIPE_KEY", "WEBHOOK_SECRET"]
},
"worker": {
"source": { "repo": "github.com/myorg/worker.git", "ref": "v1.4.0" },
"type": "app",
"runtime": "node",
"port": 8080,
"needs": ["rabbitmq"],
"connects_to": ["analytics-db"]
},
"analytics-db": {
"type": "database",
"engine": "mysql"
}
}
}
Monorepo example
If all your services live in a single repository, use source.path instead of source.repo:
{
"name": "monorepo-app",
"services": {
"api": {
"source": { "path": "packages/api" },
"type": "app",
"runtime": "java",
"port": 3000,
"public": true,
"needs": ["postgres"]
},
"worker": {
"source": { "path": "packages/worker" },
"type": "app",
"runtime": "java",
"port": 3000,
"needs": ["rabbitmq"]
}
}
}
Each path is relative to the project root. Each service directory must contain its own Dockerfile (or be auto-detectable by Nixpacks).
Visual Builder NEW
Don't want to write JSON by hand? Use the Visual Builder in the Create Project dialog. It lets you:
- Add app services (pick runtime, port, git repo)
- Add containers (specify a Docker image directly)
- Add database services (PostgreSQL or MySQL)
- Toggle infrastructure needs (Postgres, MySQL, Redis, RabbitMQ) with optional custom names
- Connect services via connects_to
- Declare required env vars (
requires_env) for pre-deploy validation - Toggle public access per service
The builder shows your plan limits in real time (services and databases per stack) and validates your configuration as you go. It generates the exact same stack.json that you would write manually — no features are lost.
Editing from the dashboard
You can also edit stack.json directly from the dashboard under Project Settings → Stack Contract. Changes trigger a new deployment automatically.
Validation
Swisblade validates your stack.json before every deploy:
- All
source.repoURLs must be accessible (with PAT if private) - All
connects_toreferences must point to services defined in the same file - All
needsvalues must be supported types - All variables listed in
requires_envmust exist in the project vault before deploying