Skip to content

Use Catapult globally with a project config

For small sites, I prefer installing Catapult once and keeping only the deployment configuration in the repository. The deployment remains reproducible: the host, release path, tasks and recipes are versioned with the project, without adding Catapult to every package.json.

Install the CLI globally:

bash
npm install --global @catapultjs/deploy

Then run Catapult from the project directory as usual:

bash
cata config:validate
cata deploy:setup
cata deploy

A JSON config in the project

edge-components.jrmc.dev is a static AdonisJS site. Its deploy.config.json generates the site locally, uploads the resulting static/ directory, then reloads Caddy:

json
{
  "$schema": "https://catapultjs.com/schema/deploy.schema.json",
  "version": 1,
  "recipes": ["systemd", "caddy"],
  "store": {
    "caddy_upload_path": "/etc/caddy/sites/example.com.caddy",
    "systemd_service": "caddy"
  },
  "config": {
    "keepReleases": 2,
    "hosts": [
      {
        "name": "production",
        "ssh": "deploy@example.com",
        "deployPath": "/home/deploy/example.com"
      }
    ]
  },
  "tasks": {
    "static:generate": {
      "steps": [{ "local": { "command": "npm run static:generate" } }]
    },
    "deploy:update_code": {
      "steps": [{ "upload": { "local": "static/.", "remote": "{{release_path}}" } }]
    }
  },
  "before": {
    "deploy:lock": "static:generate"
  },
  "after": {
    "deploy:publish": "caddy:reload"
  }
}

Catapult discovers deploy.config.json from the current directory. The schema URL gives editors completion and catches mistakes before a connection is opened. cata config:validate is a useful first check in a fresh clone or CI job.

The file contains no secrets: keep SSH credentials in your SSH configuration and use shared files for application secrets.

JavaScript or JSON?

Both formats are useful, but they serve different workflows.

Use JSON when the deployment is declarative: built-in recipes, serializable settings, command steps and pipeline placement. It has no package imports, which makes it the right format for a global Catapult installation.

Use JavaScript or TypeScript when the deployment needs hooks, local recipes, conditions or arbitrary code. Those files import @catapultjs/deploy, so install Catapult in that project and run it with npx cata. That keeps the imported API and the config on the same version.

bash
npm install --save-dev @catapultjs/deploy
npx cata deploy

The config stays in the repository in both cases. The choice is simply between a portable, schema-validated JSON file and the full flexibility of executable configuration. See the JSON configuration guide for the complete declarative format.