Meridian handbook
For agents

For agents

Start here if you are a coding agent building or changing a Meridian website. What Meridian is, the golden rules, how to read the rest of the handbook from the binary, and the change, check, render loop.

This section is written for you, the coding agent. Read this page first, then Rules and Workflow. Every command below is real and every example has passed engine-dmo check. If something here disagrees with what the binary tells you, the binary wins: it is the engine you are running.

What Meridian is

Meridian is a self-hosted content engine for place-based websites, shipped as one binary per bundle. engine-cms is the core content platform; engine-dmo is the core plus the destination-marketing modules (directory, organisations and memberships, the member portal, claims, promotions, landing pages, affiliates, paid listings, member reports). A project is a directory: YAML configuration under config/, Pongo2 templates under templates/, seed content under seed/ and static files under public/. The binary reads the project, reconciles a PostgreSQL database with it, and serves the public sites, the staff admin (at /studio), the APIs and the background jobs from one process. You build a website by editing files and running engine commands. You never write Go for an ordinary site, and you never touch the database directly.

The commands on these pages use engine-dmo. engine-cms takes the same commands for every core feature; only the DMO modules are missing from it.

The golden rules

  1. Change configuration with the engine, not around it. Use the engine-dmo dev verbs (dev type add, dev field add, dev route add and the rest) where one exists, or edit the YAML and run engine-dmo check --fix. Never write SQL, never edit the database, never invent or copy an id:.
  2. Secrets are only ever ${VAR}. Passwords, keys and tokens never appear as literal values in any file under config/.
  3. Plan before you apply. engine-dmo schema plan before engine-dmo schema apply. A destructive plan is a decision for a person, not for you.
  4. Templates are autoescaped and checked. No |safe, no inline event handlers, no variables inside <script> except through |json, every link through |url or a link helper, every visible string through t(). The layout prints {{ head() }} and {{ jsonld() }}.
  5. One h1 per page, a label for every control, alt text for every image, a skip link and a language on <html>. Accessibility is part of done, not a later pass.
  6. Verify with the engine, not by reading your own output. engine-dmo check after every change, engine-dmo render <path> --json for every route you touch, engine-dmo a11y audit --all before you hand back.
  7. Do not edit generated files. AGENTS.md, .claude/skills/meridian*/SKILL.md and .meridian/ are rewritten by the engine.
  8. Describe only what the engine does. If a feature is not in this handbook or in engine-dmo help --json, it does not exist. Say so to the person rather than faking it in a template.

Rules gives every rule with its reason and what breaks when you ignore it.

How to read more

The handbook is on the web as Markdown, and the binary describes the project. You need no browser, but you need network access to read the handbook:

ReadGives you
https://docs.cherwell.studio/llms.mdx/agents/rules/content.mdOne handbook page as Markdown. Any page’s path works, such as templates/filters
https://docs.cherwell.studio/llms.txtEvery page by title, address and description
https://docs.cherwell.studio/llms-full.txtThe whole handbook as one Markdown file; search it for a word to find a page
engine-dmo guideThis project: its rules, sites, routes, types with field ids, template globals and filters, generated from the configuration
engine-dmo describe project --jsonSites, locales, types, routes, endpoints, tiers and roles, with their ids
engine-dmo describe type <key> --jsonOne type’s fields at every depth, with ids, parameters and options
engine-dmo describe fieldtypes --jsonEvery field type, its parameters and what it stores
engine-dmo template api --jsonEvery global, function, filter, tag and component a site’s templates may use
engine-dmo help --jsonEvery command with its arguments, flags and exit codes
engine-dmo config schema --file <kind>The JSON Schema of one configuration file kind (site, routes, schema, endpoints and so on)

Read Commands for agents for what each returns and when to use it.

The handbook describes the current engine. If you cannot reach it, ask the person for its pages as files. If a page disagrees with the engine in the project, help --json, describe and template api come from the binary, so they are the source of truth for it; engine-dmo version says which engine that is.

Most read commands load the configuration, which means every ${VAR} in it without a default must be set, even to a placeholder, before they run. The engine never reads a .env file. See What each command needs.

The loop

Every change, however small, goes round the same loop:

  1. Change one thing: a verb, a YAML edit or a template.
  2. Check: engine-dmo check. Exit 0 means valid; exit 3 means invalid, with every problem listed at its file, line and column. Fix every error, and read every line it prints: the closing summary (0 errors, 0 warnings) counts configuration warnings only, so template warnings (a missing head(), a missing string, an uncredited image) are printed above a summary that says 0 warnings, and check --json leaves them out altogether.
  3. Apply, when configuration changed and a database is connected: engine-dmo schema plan, then engine-dmo schema apply (or pass --apply to the verb). Skip this when engine-dmo dev up is running in the project, since it applies safe plans itself.
  4. Render every route the change can affect: engine-dmo render <path> --json. Read status, errors, warnings and a11y. Exit 1 means the page answered 400 or more, or failed to render.
  5. Repeat until check is clean and every page renders with empty errors and a11y.
flowchart LR
  change["Change one thing<br/>(verb, YAML or template)"] --> check{"engine-dmo check<br/>exit 0?"}
  check -- "no: fix every error" --> change
  check -- yes --> apply["schema plan,<br/>then schema apply"]
  apply --> render{"render path --json:<br/>errors and a11y empty?"}
  render -- "no: fix" --> change
  render -- yes --> done["Next change, or<br/>Checklists"]
engine-dmo dev field add walk distanceKm --type number --label "Distance (km)" --param min=0 --apply
engine-dmo check
engine-dmo render /walks/cherwell-towpath --json

When something fails, look the message up in Troubleshooting. When you think you are finished, work through Checklists.

The pages in this section

PageAs MarkdownFor
Ruleshttps://docs.cherwell.studio/llms.mdx/agents/rules/content.mdEvery rule, why, and what breaks
Workflowhttps://docs.cherwell.studio/llms.mdx/agents/workflow/content.mdThe order of work from a brief to a deployable site
Commands for agentshttps://docs.cherwell.studio/llms.mdx/agents/commands/content.mdWhat each command returns and needs
Recipeshttps://docs.cherwell.studio/llms.mdx/agents/recipes/content.mdChecked examples of common tasks
Troubleshootinghttps://docs.cherwell.studio/llms.mdx/agents/troubleshooting/content.mdEach error message and its fix
Checklistshttps://docs.cherwell.studio/llms.mdx/agents/checklists/content.mdWhat done means, with the command that proves each item
The project skill and AGENTS.mdhttps://docs.cherwell.studio/llms.mdx/agents/project-skill/content.mdThe generated guidance files