Skip to content

Recipes

A recipe is a production-shaped service definition. It carries the decisions of the stack it came from: dependency choices, dockerfile targets, a dev override, a health endpoint, admin tooling, deploy configuration. mx add applies all of it in one motion.

Terminal window
mx recipes list # what is installed
mx recipes info rust-api # options, features, services
mx add api --recipe rust-api --domain api.localhost # apply it
RecipeVersionApplyWhat it carries
astro2.0✅Astro 5 with Vue 3 islands, SSR, shadcn-vue, PrimeVue, global state, Cloudflare deployment. Brings db and redis.
laravel12.0✅Laravel 12 + Octane (Swoole), Filament admin, Inertia.js SSR. Brings a worker, a scheduler, db and redis.
nuxt3.15✅Nuxt 3 SSR/SSG with the Nitro server and Tailwind CSS. Standalone.
rust-api1.0✅Actix-web + SQLx, hexagonal architecture. Brings db and redis.
rust-leptos1.0✅Leptos SSR on Actix-web with shadcn-ui, actor model, Postgres and Redis.
rust-worker1.0✅Job worker on Redis pub/sub with Postgres and local LLM evaluation.
zola1.0✅Zola static site generator. Single binary, no runtime dependencies.

mx new, mx add <svc> --recipe <r>, make dev. No hand edit in between, for every recipe that brings Postgres with it.

That is new. scripts/init.sh used to copy .env.secrets.template verbatim, leaving DB_USER, DB_PASSWORD and DB_NAME empty, and Postgres refuses to initialize with an empty password. scripts/generate-secrets.sh is now the single generation point every recipe shares: make init runs it, make dev runs make init, and it fills only what is still empty or still a placeholder. See Compose & env conventions.

astro, nuxt and zola run a framework initializer, and by default a second mx add over a service that already has an app skips it and says so. To start over from the framework’s own starter:

Terminal window
mx add site --recipe astro --opt force_init=true

This deletes apps/site/ and re-runs the initializer before mx’s wiring is layered back on. Destructive by design, and it refuses any target_dir that escapes the project rather than following it outward.

mx add reads the recipe manifest and works through it in order:

  1. Options: defaults from the manifest, overridden by --domain and any --opt key=value. mx recipes info <name> lists what a recipe accepts; rust-api, for example, takes rust, port and domain.
  2. Placeholders: {{SERVICE_NAME}}, the port, the domain and the rest are substituted through every template.
  3. Framework scaffold (init_app, where a recipe declares one): astro, nuxt and zola run the framework’s own initializer here. mx add prints Scaffolding the app… and then the command it used, or Scaffolder skipped: <dir> already holds an app when the target is not empty. This step comes first, so mx’s own wiring layers on top of the starter files and wins every collision with them.
  4. Directories: any part of the app’s source tree the scaffolder did not create is filled in.
  5. Templates: the app files, docker/compose/<service>.yml and <service>.dev.yml, docker/dockerfiles/<service>/app and app.prod, and docker/.config/.env.<service>.
  6. Router labels: the Host() rule for your --domain and the devmesh-traefik wiring.
  7. Post-install: anything the recipe declares, such as generating secrets.

Recipes that need backing services also drop db.yml / redis.yml in, once.

A scaffolder command has to be non-interactive, because mx add runs it without a terminal. The shipped defaults carry the flags that make that true, and a command that exits 0 while leaving the target empty is treated as a failure rather than a success, with the command, its working directory and both streams reported. To use a different starter, pass your own: mx add site --recipe astro --opt init_cmd='...'.

The corpus has the long-form version of this, including how recipes and the build system fit together:

→ mx recipes and build

Recipes are directories of templates plus a recipe.json manifest that declares options, placeholders, directories, templates, an optional init_app command and optional post-install steps. The full authoring guide (manifest schema, placeholder rules, the conformance tests a recipe has to pass) is in the corpus:

→ Recipe Authoring Guide

Also useful while authoring: Docker assembly guide for the dockerfile and compose halves, and Compose & env conventions for what your generated compose files have to honour.

mx recipes pull, mx recipes versions and mx recipes cache work against Unyform-hosted blueprints. That path is optional and needs an account; local recipes need neither. See Remote blueprints.