Checklists
What done means for a coding agent handing a Meridian site back, as checklists with the command that proves each item, covering the project check, every route rendering, accessibility, content, SEO, performance, deploy configuration and secrets.
Work through every list before you say a site is finished. Each item names the command that proves it. When an item cannot be proved (no database, no running server, a decision only the person can make), say so in your report instead of ticking it.
The project
-
engine-dmo checkexits 0. -
engine-dmo check --strictexits 0. - The text output of
engine-dmo checkhas nowarning:line for a template, or each one left is explained. The summary,--strictand--jsondo not count template warnings, so read the lines. -
engine-dmo seed verifysays the seed matches the schema, andengine-dmo seed applyon an empty database exits 0 (onlyapplychecks field values). - On
engine-dmo, a site with no partner businesses has the member portal turned off (portal: { mode: "off" }inconfig/portal/portal.yaml). -
engine-dmo schema planexits 0 with “No changes” (the database matches the files). - No
id:was typed by hand or copied;git diffshows ids only where a verb orcheck --fixwrote them. -
AGENTS.mdand the skills were not edited by hand (regenerate them withengine-dmo guide --out AGENTS.mdandengine-dmo guide --skill --out .claude/skills/meridian-project/SKILL.mdif in doubt). - No file under
storage/,public/build/,node_modules/,.meridian/or any.envis committed.
Every route renders
-
engine-dmo a11y audit --allreports 0 failures on every site (--site <key>for each). It renders every page the sitemap would list, plus the home page, whether or notseo.sitemap.enabledis on, and fails any that does not answer 200. - Pages outside the sitemap render: the search page with and without a query, each index page filtered by each facet, the last page of each paginated index, and the 404 page (
engine-dmo render /no-such-page --jsonanswers 404 with your template and emptyerrors). - Every locale renders:
engine-dmo render <path> --locale <code> --jsonfor one page of each type. - Every page that runs
query()has rendered (a non-indexed field fails only at render). - Every
render --jsonshows"errors": []and"status": 200. A 301 still exits 0, withkind: redirectand a non-emptya11y(a page has exactly one h1, this one has 0), anda11y audit --pathon one failshtml-langandpage-title. Neither is a defect in the page: use the address it redirects to.
Accessibility
-
engine-dmo a11y audit --allreports 0 warnings as well as 0 failures. -
render --jsonshows"a11y": []on each kind of page. - Every page:
langanddiron<html>, oneh1, a skip link to<main id="main">, labelled<nav>landmarks,aria-current="page"on the current menu item. - Every form control has a visible label; errors are summarised and linked; required fields are marked in text, not colour alone.
- Every library image has alt text in every locale (or is marked decorative);
engine-dmo media statsshows alt text coverage. - Your CSS keeps text contrast at 4.5:1 (3:1 for large text and interface parts), shows a visible focus outline, and reflows at 320 CSS pixels wide.
-
engine-dmo a11y statement --out accessibility-statement.htmlwritten for the person to complete, and a page for it in the footer menu. - You told the person a manual pass (keyboard only, a screen reader, 200% and 400% zoom) is still needed: the automated checks are evidence, not conformance.
Content
- Every routed type has published documents with realistic text, within each field’s limits.
- Every page the navigation links to exists and is published in every locale it is linked from.
- Every string the templates print is in
config/strings/<locale>.yamlfor every enabled locale (checklists missing keys). - Every label in the schema has every enabled locale (
checkwarns otherwise). - Every label
checkdoes not warn about has every enabled locale too: endpoint input labels inendpoints.yaml, navigation item labels inseed/navigation/, and the first option of each select. - Every email template has its text in each enabled locale (email templates have no
t(); see Enquiry form). - Photographs are the person’s own, licensed and credited; none is a generated image presented as a real place.
- A staff user exists or the person knows how to create one:
engine-dmo user create --email ... --name ....
SEO
-
base.htmlprints{{ head() }}once in<head>(title, description, canonical, hreflang, robots, Open Graph). -
base.htmlprints{{ jsonld() }}once in<head>. Prove it:engine-dmo render <path> | grep -c 'application/ld+json'prints 1 on an entry page and an index page.checkwarns only when a type has astructured_datablock, and the warning does not fail it. - Every routed type that is a place, an event or an article has a
structured_datablock, andengine-dmo check --strictpasses with it (SEO and structured data). -
seo.title_templateis set insite.yaml, so titles carry the site’s name:engine-dmo render <path> | grep '<title>'. -
seo.sitemap: { enabled: true }is set. It defaults to off, when/sitemap.xmlanswers 404 anda11y audit --allstill passes:engine-dmo render /sitemap.xml --jsonanswers 200. -
seo.robots: { enabled: true }is set. It defaults to off, when/robots.txtanswers 404:engine-dmo render /robots.txt --jsonanswers 200 and names the sitemap. - Each type’s documents have a meaningful
summary(used as the meta description), or the type has anseofield that is filled. -
render --jsonof an entry page shows a canonical on the site’s configured domain and, on a multilingual site,hreflangfor each published locale andx-default. - Filtered index pages are
noindex(the engine does this; check it is not overridden). -
server.base_urlis the real public origin in production.
Performance
- Every library image goes through
img(),picture()orfigure()with a declared transform; only the main image of a page haspriority=true. -
render --jsonimagesshows sensiblesizesand no image downloads far wider than it displays;engine-dmo dev status --jsonlists oversized images whendev uphas run. -
render --jsonqueriesdoes not grow with the number of items on the page. The engine’s own work is a steady baseline: about 4 to 8 statements for a 404, about 20 for a plain page, 30 to 45 for a page with images, navigation or its ownquery(), and an index of 24 items ran 18, the same as an index of one. A count in those ranges is fine. The problem to look for is onesql_summaryrepeated once per item, or a count that rises when you add items: aquery()inside a loop. Usewith()or one query outside the loop. - Stylesheets and scripts are linked through
assets.url()so they carry a version; no inline executable scripts. - Expensive repeated fragments use
{% cache %}where the content allows (Caching).
Deploy configuration
-
ENVIRONMENT=production engine-dmo check --no-dbexits 0. -
server.security.signing_key: ${SIGNING_KEY},server.base_urlfrom the environment,server.trusted_proxiesmatching the reverse proxy (orreal_ip_header: ""). - A real mail driver (
smtp,postmark,sesorresend) withmail.from; staff two-factor sign-in left on. - Storage chosen for production (a persistent volume for
filesystem, ors3) (Storage and media). - A search service configured, or the person told the search page runs in browse mode.
- The deploy sequence written down for the person: back up,
migrate up,schema apply,serve,health --readiness --wait 60s,warm(Deploying). - Extensions, if any, built for the production engine’s exact build.
Secrets
-
grep -rnfor passwords, keys and tokens underconfig/finds none: every secret is a bare${VAR}(checkenforces this for known secret paths; check custom ones yourself). - No secret in templates, seed files,
public/, commit messages or your report. -
.envis in.gitignore;.env.examplelists every variable with placeholder values only. - Your report lists every environment variable the person must set for production, without values.
The report
Tell the person what you built, how to run it (engine-dmo dev up, the URL, how to sign in), what you verified with which command, what you could not verify and why, the environment variables to set, and every decision left to them.
Troubleshooting
The errors a coding agent meets in a Meridian project (from check, the dev verbs, schema plan and apply, seed, render, the accessibility audit and server start), what each message means and the exact fix, with the MRD error codes.
The project skill and AGENTS.md
The agent guidance files a Meridian project keeps (AGENTS.md, the meridian-project skill and the meridian skill), what writes and regenerates each, and the exact short section to paste into an AGENTS.md or skill a project already has.