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
- Change configuration with the engine, not around it. Use the
engine-dmo devverbs (dev type add,dev field add,dev route addand the rest) where one exists, or edit the YAML and runengine-dmo check --fix. Never write SQL, never edit the database, never invent or copy anid:. - Secrets are only ever
${VAR}. Passwords, keys and tokens never appear as literal values in any file underconfig/. - Plan before you apply.
engine-dmo schema planbeforeengine-dmo schema apply. A destructive plan is a decision for a person, not for you. - Templates are autoescaped and checked. No
|safe, no inline event handlers, no variables inside<script>except through|json, every link through|urlor a link helper, every visible string throught(). The layout prints{{ head() }}and{{ jsonld() }}. - One
h1per 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. - Verify with the engine, not by reading your own output.
engine-dmo checkafter every change,engine-dmo render <path> --jsonfor every route you touch,engine-dmo a11y audit --allbefore you hand back. - Do not edit generated files.
AGENTS.md,.claude/skills/meridian*/SKILL.mdand.meridian/are rewritten by the engine. - 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:
| Read | Gives you |
|---|---|
https://docs.cherwell.studio/llms.mdx/agents/rules/content.md | One handbook page as Markdown. Any page’s path works, such as templates/filters |
https://docs.cherwell.studio/llms.txt | Every page by title, address and description |
https://docs.cherwell.studio/llms-full.txt | The whole handbook as one Markdown file; search it for a word to find a page |
engine-dmo guide | This project: its rules, sites, routes, types with field ids, template globals and filters, generated from the configuration |
engine-dmo describe project --json | Sites, locales, types, routes, endpoints, tiers and roles, with their ids |
engine-dmo describe type <key> --json | One type’s fields at every depth, with ids, parameters and options |
engine-dmo describe fieldtypes --json | Every field type, its parameters and what it stores |
engine-dmo template api --json | Every global, function, filter, tag and component a site’s templates may use |
engine-dmo help --json | Every 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:
- Change one thing: a verb, a YAML edit or a template.
- 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 missinghead(), a missing string, an uncredited image) are printed above a summary that says0 warnings, andcheck --jsonleaves them out altogether. - Apply, when configuration changed and a database is connected:
engine-dmo schema plan, thenengine-dmo schema apply(or pass--applyto the verb). Skip this whenengine-dmo dev upis running in the project, since it applies safe plans itself. - Render every route the change can affect:
engine-dmo render <path> --json. Readstatus,errors,warningsanda11y. Exit 1 means the page answered 400 or more, or failed to render. - Repeat until check is clean and every page renders with empty
errorsanda11y.
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
| Page | As Markdown | For |
|---|---|---|
| Rules | https://docs.cherwell.studio/llms.mdx/agents/rules/content.md | Every rule, why, and what breaks |
| Workflow | https://docs.cherwell.studio/llms.mdx/agents/workflow/content.md | The order of work from a brief to a deployable site |
| Commands for agents | https://docs.cherwell.studio/llms.mdx/agents/commands/content.md | What each command returns and needs |
| Recipes | https://docs.cherwell.studio/llms.mdx/agents/recipes/content.md | Checked examples of common tasks |
| Troubleshooting | https://docs.cherwell.studio/llms.mdx/agents/troubleshooting/content.md | Each error message and its fix |
| Checklists | https://docs.cherwell.studio/llms.mdx/agents/checklists/content.md | What done means, with the command that proves each item |
| The project skill and AGENTS.md | https://docs.cherwell.studio/llms.mdx/agents/project-skill/content.md | The generated guidance files |
Error codes
Every stable MRD error code the engine reports, with its cause and its fix.
Rules
Every rule a coding agent must follow in a Meridian project, why it exists and exactly what breaks when it is ignored, covering configuration, ids, secrets, schema changes, content, templates, accessibility, generated files and production.