Skip to content

Configuration ​

portico.yaml lists the services Portico runs and routes. Every command reads it, so portico status or portico down from another terminal act on the same project.

At a Glance ​

  • Portico looks for portico.yaml or .portico.yaml in the current directory, then in each parent, stopping at the git root.
  • -c, --config FILE points any command at a specific file.
  • Without a file, Portico runs on its defaults and whatever --run and --route add.

Kinds of Services ​

Each entry under services is one of four kinds, picked by the key it sets:

yaml
services:
  web:
    run: npm run dev -- --port {port}
    dir: frontend
    route: /
  api:
    port: 3200
  config-server:
    image: registry.example.com/config-server
    tag: "2.4"
    port: 8080
    route: /config
  stack:
    compose: ./compose.yaml
  • run: a shell command Portico starts, in dir if set. {port} in the command becomes the service's port, which is also set as PORT. Leave port out and Portico picks a free one; set port: none for a worker that serves nothing.
  • image: a container. port is the port inside the container; Portico publishes it on a free local port.
  • compose: a compose file. Every port its services publish gets a route (see Routing).
  • Only port: something you start yourself, such as an API under a debugger. Portico routes to it but never starts or stops it.

Service names use a-z, 0-9, _, . and -. portico and nginx are reserved.

Commands and Their Environment ​

A run command runs through sh -c, so pipes, && and variables work. Portico adds a few variables to the environment it inherits:

VariableValue
PORTThe service's port, unless it has port: none.
PYTHONUNBUFFERED1, so Python output shows up as it's printed.
FORCE_COLOR1 when Portico prints to a terminal without --raw.

Most dev servers read .env themselves. For one that doesn't, load it in the command:

yaml
services:
  api:
    run: set -a; . ./.env; set +a; ./start

Write a Starter With portico init ​

portico init writes portico.yaml from what it finds in the current directory:

  • A compose file: the first of compose.yaml, compose.yml, docker-compose.yaml and docker-compose.yml, added as a service named stack.
  • package.json dev scripts: in the directory itself, then in web, frontend, client, app and ui, then in every other subdirectory. The first one found gets the / route.

For each dev script, init uses the package manager its lock file points at (pnpm, Yarn or Bun, else npm), and passes the port the way the framework expects:

DependencyPort flags
next-p {port}
vite--port {port} --strictPort
nuxt, astro--port {port}

In a terminal, init asks which of the services to add. -y, --yes adds them all, and --force replaces an existing portico.yaml. When it finds nothing, it writes a single example service to edit.

Validation ​

Portico checks the whole file before starting anything, and lists every problem at once. Unknown keys are errors too, so a typo like rout: fails instead of being ignored.

The schema on the first line of the file gives your editor the same checks, with autocompletion:

yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/kloudkit/portico/main/portico.schema.json

Next Steps ​

Released under the MIT License