app.json Schema
app.json is an optional manifest at the root of your repo that tells Watasu how to bootstrap an app. It’s the source of truth for review apps, and useful anywhere you want repeatable provisioning.
Top-level fields
Section titled “Top-level fields”| Field | Type | Purpose |
|---|---|---|
name | string | Display name. |
description | string | Short summary. |
logo | string (URL) | Logo image. |
website | string (URL) | Project website. |
repository | string (URL) | Source repo URL. |
keywords | array of strings | Categorization keywords. |
success_url | string | Path to redirect to after a successful bootstrap. |
env | object | Default config vars (see env). |
addons | array | Add-ons to provision (see addons). |
formation | object | Process formation defaults (see formation). |
scripts | object | Lifecycle scripts (see scripts). |
Each entry sets a config var on bootstrap.
"env": { "RAILS_ENV": { "value": "production" }, "SECRET_KEY": { "generator": "secret" }, "API_BASE": { "required": true, "description": "External API base URL" }}| Key | Purpose |
|---|---|
value | Literal value to set. |
generator | Generator to use (e.g. secret for a random string). |
required | If true, bootstrap fails unless the user supplies a value. |
description | Human-readable hint shown to the user during bootstrap. |
addons
Section titled “addons”Each entry provisions and attaches an add-on. You can use a plain string for the default plan or service:plan for a specific tier.
"addons": [ "postgresql", "postgresql:standard-0", "valkey:hobby-1", "object-storage"]For the full plan catalog, see Add-on Plans.
formation
Section titled “formation”Sets initial replica counts and pod sizes per process type.
"formation": { "web": { "quantity": 1, "size": "standard-1x" }, "worker": { "quantity": 1, "size": "standard-1x" }}| Key | Purpose |
|---|---|
quantity | Replica count. |
size | Pod size (standard-1x … standard-16x). See Pod Sizes. |
scripts
Section titled “scripts”Lifecycle scripts that Watasu runs at specific points.
"scripts": { "postdeploy": "bundle exec rails db:prepare && bundle exec rails db:seed", "pr-predestroy": "bundle exec rails app:cleanup"}| Script | When it runs |
|---|---|
postdeploy | Once after the first successful deploy. Use for migrations and seeding. |
pr-predestroy | Before a review app is torn down. Use for external cleanup. |
Keep both scripts idempotent — they may run more than once over an app’s lifetime, especially postdeploy.
Full example
Section titled “Full example”{ "name": "Example App", "description": "A Watasu app with a database, cache, and review-app setup", "repository": "https://github.com/example/example-app", "keywords": ["rails", "example"], "env": { "RAILS_ENV": { "value": "production" }, "RAILS_MASTER_KEY": { "required": true, "description": "Rails encrypted credentials key" }, "SECRET_KEY_BASE": { "generator": "secret" } }, "addons": [ "postgresql:hobby-0", "valkey:hobby-1" ], "formation": { "web": { "quantity": 1, "size": "standard-1x" }, "worker": { "quantity": 1, "size": "standard-1x" } }, "scripts": { "postdeploy": "bundle exec rails db:prepare", "pr-predestroy": "bundle exec rails app:cleanup" }}- Don’t put real secrets in
app.json. Usegenerator: secretorrequired: trueinstead. - For review apps, lean on small plans (
postgresql:hobby-0,valkey:hobby-0) — they don’t need production sizing. - Test the file with a real PR. Most issues only surface when an actual review app spins up.