← Total CMSCONTENT HISTORY

Update to Total CMS

Snapshot Nov 10, 2026 · 06:59 UTC · version 1.2.1

Collection source: downloaded plugin package.

WHAT CHANGED

Instructions updated for totalcms

Full description — Now says: writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug.

Observed in instructions or declared skills. Runtime behavior has not been tested.

Save Total CMS and check future changes in Following.

Up to 3 plugins free · no card required.

All fields and original values.

Full description

Before

Oct 24, 2026 · 13:41 UTC

or writing a T3 extension.

After

Nov 10, 2026 · 06:59 UTC

writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug.

Skill instructions

Before

Oct 24, 2026 · 13:41 UTC

or writing a T3 extension. Covers the local build workflow end to end. This skill is a copy of the one shipped with the installed CMS, so it can fall behind. At the start of a session run `vendor/bin/tcms skill:install --check`. `port...

After

Nov 10, 2026 · 06:59 UTC

writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end. This check applies only inside a Total CMS project. If you are not working in one — this skill came with a pl...

Supporting files

Before

Oct 24, 2026 · 13:41 UTC

[{"relative_path":"references/cli.md","size_in_bytes":5498},{"relative_path":"references/data-model.md","size_in_bytes":11112},{"relative_path":"references/extensions.md","size_in_bytes":4615},{"relative_path":"references/features.md","s...

After

Nov 10, 2026 · 06:59 UTC

[{"relative_path":"references/cli.md","size_in_bytes":9357},{"relative_path":"references/data-model.md","size_in_bytes":14046},{"relative_path":"references/extensions.md","size_in_bytes":5372},{"relative_path":"references/features.md","s...

Compare saved observations

Download comparison JSON

SKILL.md text changes

− removed · + added

--- before
+++ after
@@ -1,6 +1,6 @@
 ---
 name: totalcms
-description: Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, or writing a T3 extension. Covers the local build workflow end to end.
+description: Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end.
 ---
 
 # Building a Total CMS (T3) site
@@ -11,8 +11,14 @@
 
 ## Is this copy current?
 
-This skill is a copy of the one shipped with the installed CMS, so it can fall
-behind. At the start of a session run `vendor/bin/tcms skill:install --check`.
+This check applies only inside a Total CMS project. If you are not working in
+one — this skill came with a plugin and the current folder has no Total CMS CLI
+— skip it: there is no installed copy to check, and this text describes the
+latest release. When a project's own copy (in `.claude/skills/totalcms/`) is
+also loaded, follow that one: it matches the CMS version the project runs.
+
+In a project, this skill is a copy of the one shipped with the installed CMS, so
+it can fall behind. At the start of a session run `vendor/bin/tcms skill:install --check`.
 If it reports stale, run `vendor/bin/tcms skill:install` and then tell the user
 to start a new session — the text already loaded cannot replace itself. The
 stamp is a hash of the skill's own content, not the release number, so only real
@@ -49,8 +55,17 @@
 | load many objects | `vendor/bin/tcms collection:import <collection> file.json` |
 | add or change a schema | `vendor/bin/tcms schema:import schema.json`, then `schema:lint <id> --strict` |
 | create a collection | `vendor/bin/tcms collection:create …` |
+| change a collection's settings | `vendor/bin/tcms collection:update <id> --set ownerProperty=author` (or JSON on stdin) |
+| add or change an access group | `vendor/bin/tcms access-group:set <id> -` / `access-group:patch <id> -` |
 | seed structure + content together | `vendor/bin/tcms jumpstart:import file.json` |
 
+**Mailer templates, automations and Data Views are collections too**
+(`mailer`, `automations`, `dataviews`), so the same `object:*` commands read and
+change them: `vendor/bin/tcms object:patch mailer <id> -` edits one mailer field
+and leaves the rest. Run `vendor/bin/tcms collection:list` to see every
+collection, the reserved ones included, before deciding that something has no
+command.
+
 A save through the CLI validates the object against its schema, fills in what
 the schema derives (default types, autogen ids, `created`/`updated`
 timestamps, image and video metadata), updates the collection's `.index.json`
@@ -94,18 +109,25 @@
    the router serves and flags conflicts. `vendor/bin/tcms builder:routes --json` to script.
 2. **If Site Builder isn't set up yet,** scaffold a starter:
    `vendor/bin/tcms builder:init <starter>` where `<starter>` is `business`, `blog`,
-   `portfolio`, or `minimal`. Add `--frontend` to also install the Vite pipeline.
+   `portfolio`, or `minimal`. Add `--frontend` to also install and build the Vite pipeline.
    This copies templates, ensures the `builder-pages` collection, and seeds demo pages.
 3. **Edit templates** on the filesystem under
    `builder/{layouts,pages,partials,macros}/*.twig` when a project-root `builder/`
    directory exists (git-managed mode: it wins over `tcms-data/`, and the admin's
-   template editor is read-only), otherwise `tcms-data/builder/`. Twig global is `cms`;
+   template editor is read-only unless `env` is `dev`), otherwise `tcms-data/builder/`. Twig global is `cms`;
    builder helpers are `cms.builder.nav()`, `cms.builder.url(id, params)`,
    `cms.builder.css/js/asset()`. The layout's `<head>` carries
    `{% block seo %}{{ cms.seo.head(page|default(null)) }}{% endblock %}` — it emits
    title, description, canonical, Open Graph and JSON-LD, so a layout must not also
    hand-write `<title>` or `<meta name="description">`. See `references/site-builder.md`.
-4. **Add a page record.** A page is an object in the `builder-pages` collection.
+4. **Credit line.** When you write a layout's footer, add `{{ cms.badge.text() }}`:
+   a subtle inline "Powered by Total CMS" link in the site's own text color
+   (`cms.badge.text({theme: 'mono'})` if the colored flame clashes with the design).
+   The starters' footers already carry it. On a site a designer is building for a
+   client, credit the designer instead with `cms.badge.builtByText('<handle>')`; if
+   they have no totalcms.co handle, use `cms.badge.text()`. Either way, say in your
+   summary that you added it, and leave it out or remove it whenever the user asks.
+5. **Add a page record.** A page is an object in the `builder-pages` collection.
    Create it one of these ways:
    - `echo '{"id":"about","title":"About","route":"/about","template":"pages/page.twig"}' | vendor/bin/tcms object:create builder-pages -` (one object, file or stdin), or
    - the **admin UI** (Site Builder → Pages), or
@@ -113,8 +135,8 @@
    - `vendor/bin/tcms jumpstart:import <file>` for bulk seeding.
    Key `builder-pages` fields: `route`, `template`, `title`, `draft`, `data` (free-form
    JSON exposed as `page.data.*`). Full list in `references/site-builder.md`.
-5. **Preview:** `php -S localhost:8080 -t public public/index.php` and visit the
-   page's `route`. Pass `public/index.php` as the router script — without it the
+6. **Preview:** `php -S localhost:8080 -t public public/index.php` and visit the
+   page's `route`. Give `public/index.php` as the router script — without it the
    built-in server only serves files that exist on disk and never reaches the page
    router, so every builder page 404s. Clear caches after template changes if
    needed: `vendor/bin/tcms cache:clear`. Restart the server after adding page
@@ -127,8 +149,11 @@
 It demonstrates every field type with the settings and help text that go with it.
 Pick fields by the shape of the value (`date`, `toggle`, `select`, `number`, `image`…);
 `text` is the last resort. Write every `help` and `description` as a brief to a
-writer who cannot see the site — agents read them through MCP. Rules, the
-five meanings of "category", and the SEO card: `references/data-model.md`.
+writer who cannot see the site — agents read them through MCP. **Do not add a
+`sort` or `order` number field** to put a list in order: sort by the properties
+the data already has, rank a property's values with `manualSort`, and only then
+add a property named for why an item moves (`featured`, `weight`). Rules, the
+five meanings of "category", ordering, and the SEO card: `references/data-model.md`.
 
 The admin enforces these for you. They only bite when you author JSON that the
 CLI then imports — JumpStart files, `collection:import` payloads, API bodies —
@@ -157,15 +182,26 @@
 
 Two rules prevent the two worst mistakes:
 
-- **Patch, don't replace.** When editing a live site through its MCP server,
-  prefer `patch_object` (merges only the fields you send). `update_object` is a
-  FULL replace — if you must use it, fetch the complete record with
-  `get_object` + `format: "html"` first, edit, strip the decorated `url` key,
-  and write the whole body back. Details: `references/mcp-content.md`.
+- **Send only what changes.** When editing a live site through its MCP
+  server, use `patch_object` with just the changed fields. `update_object`
+  merges the same way (omitted fields keep their values). If you write back a
+  fetched record, fetch it with `format: "html"` and strip the decorated `url`
+  key first. Media fields take metadata edits only (alt text, tags); naming
+  every gallery image once also reorders the gallery. Details:
+  `references/mcp-content.md`.
 - **After launch, the server owns content.** Local seed files go stale by
   design — never re-import them over live data. Use `pull`/`push` (dry-run
   first; filters are exclusive). Details: `references/going-live.md`.
 
+## When something looks like a Total CMS bug
+
+Do not tell the user "this is a bug in Total CMS" until you have worked through
+`references/troubleshooting.md`. Most apparent bugs are hand-written files,
+stale caches, schema mistakes or hosting limits, and are fixed on this side.
+For a confirmed bug, write the report in the shape that file gives, so it
+carries the version, environment and log excerpt support needs, and tell the
+user to email it to support@totalcms.co.
+
 ## Reference files (read on demand)
 
 | When you are… | Read |
@@ -173,9 +209,11 @@
 | running any `tcms` command / scripting with `--json` | `references/cli.md` |
 | editing builder templates, routes, or page records | `references/site-builder.md` |
 | setting up or building frontend assets | `references/frontend.md` |
-| modeling data — collections, schemas, field choice, descriptions | `references/data-model.md` |
+| modeling data — collections, schemas, field choice, descriptions, ordering a list | `references/data-model.md` |
+| letting signed-in members add and edit their own content (ownership, review, account pages) | `references/member-content.md` |
 | wondering whether T3 already does something (SEO, forms, automations, search, feeds, auth…) | `references/features.md` |
 | writing or reviewing an extension | `references/extensions.md` |
 | reading/writing content via the site's MCP server | `references/mcp-content.md` |
+| hitting an error, or about to call something a Total CMS bug | `references/troubleshooting.md` |
 | launching, syncing with production (`push`/`pull`) | `references/going-live.md` |
 | needing an exact field option / Twig signature | `vendor/totalcms/cms/resources/docs/<section>/` (or MCP) |
Full technical diff · 3 changed fields

changed /description

BEFORE
"Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, or writing a T3 extension. Covers the local build workflow end to end."
AFTER
"Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end."

changed /included_files

BEFORE
[
  {
    "relative_path": "references/cli.md",
    "size_in_bytes": 5498
  },
  {
    "relative_path": "references/data-model.md",
    "size_in_bytes": 11112
  },
  {
    "relative_path": "references/extensions.md",
    "size_in_bytes": 4615
  },
  {
    "relative_path": "references/features.md",
    "size_in_bytes": 10694
  },
  {
    "relative_path": "references/frontend.md",
    "size_in_bytes": 1383
  },
  {
    "relative_path": "references/going-live.md",
    "size_in_bytes": 3165
  },
  {
    "relative_path": "references/mcp-content.md",
    "size_in_bytes": 3236
  },
  {
    "relative_path": "references/site-builder.md",
    "size_in_bytes": 5545
  }
]
AFTER
[
  {
    "relative_path": "references/cli.md",
    "size_in_bytes": 9357
  },
  {
    "relative_path": "references/data-model.md",
    "size_in_bytes": 14046
  },
  {
    "relative_path": "references/extensions.md",
    "size_in_bytes": 5372
  },
  {
    "relative_path": "references/features.md",
    "size_in_bytes": 21385
  },
  {
    "relative_path": "references/frontend.md",
    "size_in_bytes": 3038
  },
  {
    "relative_path": "references/going-live.md",
    "size_in_bytes": 3267
  },
  {
    "relative_path": "references/mcp-content.md",
    "size_in_bytes": 6224
  },
  {
    "relative_path": "references/member-content.md",
    "size_in_bytes": 7878
  },
  {
    "relative_path": "references/site-builder.md",
    "size_in_bytes": 6319
  },
  {
    "relative_path": "references/troubleshooting.md",
    "size_in_bytes": 6332
  }
]

changed /skill_md_contents

BEFORE
"---\nname: totalcms\ndescription: Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, or writing a T3 extension. Covers the local build workflow end to end.\n---\n\n# Building a Total CMS (T3) site\n\nThis project **is a website** built on Total CMS, a flat-file PHP CMS. There is\n**no database** — all content is JSON under `tcms-data/`. Configure via\n`config/tcms.php` (deep-merged — specify only keys you change).\n\n## Is this copy current?\n\nThis skill is a copy of the one shipped with the installed CMS, so it can fall\nbehind. At the start of a session run `vendor/bin/tcms skill:install --check`.\nIf it reports stale, run `vendor/bin/tcms skill:install` and then tell the user\nto start a new session — the text already loaded cannot replace itself. The\nstamp is a hash of the skill's own content, not the release number, so only real\nchanges to the skill flag it.\n\n## Where things are\n\nT3 ships in two layouts. Check which one you are in before running anything.\n\n- **Composer install** — the default the rest of this skill assumes. CLI `vendor/bin/tcms`; CMS code and docs under `vendor/totalcms/cms/`; config `config/tcms.php` at the project root. **Never edit `vendor/`** — an update replaces it. <!-- composer-paths -->\n- **Zip install** — the CMS *is* the folder you are in (conventionally `tcms/`).\n  CLI `php resources/bin/tcms`, run from that folder; docs `resources/docs/`;\n  config `config/tcms.php` inside it; content in `../tcms-data/` beside it. An\n  update replaces the folder's `config/ public/ resources/ src/ vendor/`\n  wholesale, so **never add files inside them**.\n\nIf this skill was installed by `skill:install` on a zip install, the paths\nthroughout it are already rewritten for that layout.\n\nMost commands accept `--json` for machine-readable output — prefer it when\nscripting. Run `vendor/bin/tcms list` to see everything.\n\n## Write through the CLI, never to the files\n\n`tcms-data/` is a store, not an editing surface. It is tempting to create or\nedit the JSON files in it directly — it usually appears to work, which is what\nmakes it dangerous. **Always go through the CLI (or the API/MCP), which is what\nthe admin does:**\n\n| To… | Run |\n|---|---|\n| create an object | `vendor/bin/tcms object:create <collection> -` (JSON on stdin) |\n| change part of an object | `vendor/bin/tcms object:patch <collection> <id> -` |\n| load many objects | `vendor/bin/tcms collection:import <collection> file.json` |\n| add or change a schema | `vendor/bin/tcms schema:import schema.json`, then `schema:lint <id> --strict` |\n| create a collection | `vendor/bin/tcms collection:create …` |\n| seed structure + content together | `vendor/bin/tcms jumpstart:import file.json` |\n\nA save through the CLI validates the object against its schema, fills in what\nthe schema derives (default types, autogen ids, `created`/`updated`\ntimestamps, image and video metadata), updates the collection's `.index.json`\nand counts, and fires the events the rest of the system listens for (search\nindexing, automations, MCP change notifications). A file written by hand gets\nnone of that: one bad comma takes the whole collection offline, an unindexed\nobject is invisible to the admin tables, sitemaps and queries until\n`repair:index` runs, and timestamps and derived fields are simply missing.\n\nReading the files is fine (`cat`, `jq`), though `object:get --json` is the\nsame data validated. If you ever *must* touch a file — recovering data, say —\nvalidate the JSON, then run `vendor/bin/tcms repair:index <collection>` and,\nfor a schema, `schema:lint <id> --strict`.\n\nThis applies to **content and structure**. Templates under `builder/` and the\nconfig file `config/tcms.php` are files by design — edit those directly.\n\n## Where to look things up\n\nYou do **not** need to memorize field options or Twig signatures — they ship on disk:\n\n- **On-disk docs (always present):** `vendor/totalcms/cms/resources/docs/<section>/`\n  (`menu.php` is the table of contents, `search-index.json` a prebuilt index).\n  Sections: `get-started/`, `collections/`, `schemas/`, `fields/`, `site-builder/`,\n  `twig/`, `forms/`, `automations/`, `admin/`, `notifications/`, `auth/`, `apis/`,\n  `mcp/`, `extensions/`, `operations/`. `references/features.md` maps every feature\n  to its page. Grep or read these for the long tail.\n- **MCP docs server (fastest lookup):** when the official docs connector\n  (`https://totalcms.co/mcp`) is connected — it ships alongside this skill in\n  the Total CMS plugin — use `docs_search` to find pages, `docs_get` to read\n  one, and `docs_lookup(kind, name)` for exact reference entries (Twig\n  functions/filters, field types, API endpoints, schema config, CLI commands,\n  extension/builder API).\n  The on-disk docs remain authoritative and work with no connection.\n\nPrefer looking things up over guessing; training data is often stale on exact signatures.\n\n## The build loop: add a page to the site\n\n1. **See what already routes:** `vendor/bin/tcms builder:routes` lists every page\n   the router serves and flags conflicts. `vendor/bin/tcms builder:routes --json` to script.\n2. **If Site Builder isn't set up yet,** scaffold a starter:\n   `vendor/bin/tcms builder:init <starter>` where `<starter>` is `business`, `blog`,\n   `portfolio`, or `minimal`. Add `--frontend` to also install the Vite pipeline.\n   This copies templates, ensures the `builder-pages` collection, and seeds demo pages.\n3. **Edit templates** on the filesystem under\n   `builder/{layouts,pages,partials,macros}/*.twig` when a project-root `builder/`\n   directory exists (git-managed mode: it wins over `tcms-data/`, and the admin's\n   template editor is read-only), otherwise `tcms-data/builder/`. Twig global is `cms`;\n   builder helpers are `cms.builder.nav()`, `cms.builder.url(id, params)`,\n   `cms.builder.css/js/asset()`. The layout's `<head>` carries\n   `{% block seo %}{{ cms.seo.head(page|default(null)) }}{% endblock %}` — it emits\n   title, description, canonical, Open Graph and JSON-LD, so a layout must not also\n   hand-write `<title>` or `<meta name=\"description\">`. See `references/site-builder.md`.\n4. **Add a page record.** A page is an object in the `builder-pages` collection.\n   Create it one of these ways:\n   - `echo '{\"id\":\"about\",\"title\":\"About\",\"route\":\"/about\",\"template\":\"pages/page.twig\"}' | vendor/bin/tcms object:create builder-pages -` (one object, file or stdin), or\n   - the **admin UI** (Site Builder → Pages), or\n   - `vendor/bin/tcms collection:import builder-pages <file.json>` for arrays (see `references/cli.md`), or\n   - `vendor/bin/tcms jumpstart:import <file>` for bulk seeding.\n   Key `builder-pages` fields: `route`, `template`, `title`, `draft`, `data` (free-form\n   JSON exposed as `page.data.*`). Full list in `references/site-builder.md`.\n5. **Preview:** `php -S localhost:8080 -t public public/index.php` and visit the\n   page's `route`. Pass `public/index.php` as the router script — without it the\n   built-in server only serves files that exist on disk and never reaches the page\n   router, so every builder page 404s. Clear caches after template changes if\n   needed: `vendor/bin/tcms cache:clear`. Restart the server after adding page\n   records — the route index is cached in the server process.\n\n## Writing schemas and content by hand\n\n**Before writing any schema, read the reference schema** —\n`vendor/bin/tcms schema:get totalcms --json` — and copy property definitions from it.\nIt demonstrates every field type with the settings and help text that go with it.\nPick fields by the shape of the value (`date`, `toggle`, `select`, `number`, `image`…);\n`text` is the last resort. Write every `help` and `description` as a brief to a\nwriter who cannot see the site — agents read them through MCP. Rules, the\nfive meanings of \"category\", and the SEO card: `references/data-model.md`.\n\nThe admin enforces these for you. They only bite when you author JSON that the\nCLI then imports — JumpStart files, `collection:import` payloads, API bodies —\nwhich is exactly what an agent tends to write. (Authoring JSON *for the CLI to\nimport* is fine; writing it straight into `tcms-data/` is not — see \"Write\nthrough the CLI, never to the files\" above.)\n\n- **Every schema must define an `id` property**, not just list `id` in `required`.\n  A schema missing it fails with `The required properties (id) are missing`, which\n  points at your data when the bug is in the schema.\n- **Decks are dictionaries of named items, not arrays.** Each key names one item and\n  must equal that item's `id`:\n  `{\"rows\": {\"first_row\": {\"id\": \"first_row\", ...}}}`\n- **Deck item keys allow only letters, numbers, and underscores** — no hyphens, so\n  Twig can read them as `deck.first_row`. `first-row` is rejected on import.\n- **`field: \"deckTable\"`** stores exactly like a deck but edits as a table.\n\nSee `vendor/totalcms/cms/resources/docs/fields/deck.md` for the full shape.\n\n**Schema work is done when `vendor/bin/tcms schema:lint <id> --strict` is clean** —\nzero errors, zero warnings. Imports validate on the way in, but in-place edits are\nnever re-checked, and the linter flags every property missing the help text AI\nagents rely on. Fill descriptions in on the first pass, not as a follow-up.\n\n## Working against a live site\n\nTwo rules prevent the two worst mistakes:\n\n- **Patch, don't replace.** When editing a live site through its MCP server,\n  prefer `patch_object` (merges only the fields you send). `update_object` is a\n  FULL replace — if you must use it, fetch the complete record with\n  `get_object` + `format: \"html\"` first, edit, strip the decorated `url` key,\n  and write the whole body back. Details: `references/mcp-content.md`.\n- **After launch, the server owns content.** Local seed files go stale by\n  design — never re-import them over live data. Use `pull`/`push` (dry-run\n  first; filters are exclusive). Details: `references/going-live.md`.\n\n## Reference files (read on demand)\n\n| When you are… | Read |\n|---|---|\n| running any `tcms` command / scripting with `--json` | `references/cli.md` |\n| editing builder templates, routes, or page records | `references/site-builder.md` |\n| setting up or building frontend assets | `references/frontend.md` |\n| modeling data — collections, schemas, field choice, descriptions | `references/data-model.md` |\n| wondering whether T3 already does something (SEO, forms, automations, search, feeds, auth…) | `references/features.md` |\n| writing or reviewing an extension | `references/extensions.md` |\n| reading/writing content via the site's MCP server | `references/mcp-content.md` |\n| launching, syncing with production (`push`/`pull`) | `references/going-live.md` |\n| needing an exact field option / Twig signature | `vendor/totalcms/cms/resources/docs/<section>/` (or MCP) |\n"
AFTER
"---\nname: totalcms\ndescription: Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end.\n---\n\n# Building a Total CMS (T3) site\n\nThis project **is a website** built on Total CMS, a flat-file PHP CMS. There is\n**no database** — all content is JSON under `tcms-data/`. Configure via\n`config/tcms.php` (deep-merged — specify only keys you change).\n\n## Is this copy current?\n\nThis check applies only inside a Total CMS project. If you are not working in\none — this skill came with a plugin and the current folder has no Total CMS CLI\n— skip it: there is no installed copy to check, and this text describes the\nlatest release. When a project's own copy (in `.claude/skills/totalcms/`) is\nalso loaded, follow that one: it matches the CMS version the project runs.\n\nIn a project, this skill is a copy of the one shipped with the installed CMS, so\nit can fall behind. At the start of a session run `vendor/bin/tcms skill:install --check`.\nIf it reports stale, run `vendor/bin/tcms skill:install` and then tell the user\nto start a new session — the text already loaded cannot replace itself. The\nstamp is a hash of the skill's own content, not the release number, so only real\nchanges to the skill flag it.\n\n## Where things are\n\nT3 ships in two layouts. Check which one you are in before running anything.\n\n- **Composer install** — the default the rest of this skill assumes. CLI `vendor/bin/tcms`; CMS code and docs under `vendor/totalcms/cms/`; config `config/tcms.php` at the project root. **Never edit `vendor/`** — an update replaces it. <!-- composer-paths -->\n- **Zip install** — the CMS *is* the folder you are in (conventionally `tcms/`).\n  CLI `php resources/bin/tcms`, run from that folder; docs `resources/docs/`;\n  config `config/tcms.php` inside it; content in `../tcms-data/` beside it. An\n  update replaces the folder's `config/ public/ resources/ src/ vendor/`\n  wholesale, so **never add files inside them**.\n\nIf this skill was installed by `skill:install` on a zip install, the paths\nthroughout it are already rewritten for that layout.\n\nMost commands accept `--json` for machine-readable output — prefer it when\nscripting. Run `vendor/bin/tcms list` to see everything.\n\n## Write through the CLI, never to the files\n\n`tcms-data/` is a store, not an editing surface. It is tempting to create or\nedit the JSON files in it directly — it usually appears to work, which is what\nmakes it dangerous. **Always go through the CLI (or the API/MCP), which is what\nthe admin does:**\n\n| To… | Run |\n|---|---|\n| create an object | `vendor/bin/tcms object:create <collection> -` (JSON on stdin) |\n| change part of an object | `vendor/bin/tcms object:patch <collection> <id> -` |\n| load many objects | `vendor/bin/tcms collection:import <collection> file.json` |\n| add or change a schema | `vendor/bin/tcms schema:import schema.json`, then `schema:lint <id> --strict` |\n| create a collection | `vendor/bin/tcms collection:create …` |\n| change a collection's settings | `vendor/bin/tcms collection:update <id> --set ownerProperty=author` (or JSON on stdin) |\n| add or change an access group | `vendor/bin/tcms access-group:set <id> -` / `access-group:patch <id> -` |\n| seed structure + content together | `vendor/bin/tcms jumpstart:import file.json` |\n\n**Mailer templates, automations and Data Views are collections too**\n(`mailer`, `automations`, `dataviews`), so the same `object:*` commands read and\nchange them: `vendor/bin/tcms object:patch mailer <id> -` edits one mailer field\nand leaves the rest. Run `vendor/bin/tcms collection:list` to see every\ncollection, the reserved ones included, before deciding that something has no\ncommand.\n\nA save through the CLI validates the object against its schema, fills in what\nthe schema derives (default types, autogen ids, `created`/`updated`\ntimestamps, image and video metadata), updates the collection's `.index.json`\nand counts, and fires the events the rest of the system listens for (search\nindexing, automations, MCP change notifications). A file written by hand gets\nnone of that: one bad comma takes the whole collection offline, an unindexed\nobject is invisible to the admin tables, sitemaps and queries until\n`repair:index` runs, and timestamps and derived fields are simply missing.\n\nReading the files is fine (`cat`, `jq`), though `object:get --json` is the\nsame data validated. If you ever *must* touch a file — recovering data, say —\nvalidate the JSON, then run `vendor/bin/tcms repair:index <collection>` and,\nfor a schema, `schema:lint <id> --strict`.\n\nThis applies to **content and structure**. Templates under `builder/` and the\nconfig file `config/tcms.php` are files by design — edit those directly.\n\n## Where to look things up\n\nYou do **not** need to memorize field options or Twig signatures — they ship on disk:\n\n- **On-disk docs (always present):** `vendor/totalcms/cms/resources/docs/<section>/`\n  (`menu.php` is the table of contents, `search-index.json` a prebuilt index).\n  Sections: `get-started/`, `collections/`, `schemas/`, `fields/`, `site-builder/`,\n  `twig/`, `forms/`, `automations/`, `admin/`, `notifications/`, `auth/`, `apis/`,\n  `mcp/`, `extensions/`, `operations/`. `references/features.md` maps every feature\n  to its page. Grep or read these for the long tail.\n- **MCP docs server (fastest lookup):** when the official docs connector\n  (`https://totalcms.co/mcp`) is connected — it ships alongside this skill in\n  the Total CMS plugin — use `docs_search` to find pages, `docs_get` to read\n  one, and `docs_lookup(kind, name)` for exact reference entries (Twig\n  functions/filters, field types, API endpoints, schema config, CLI commands,\n  extension/builder API).\n  The on-disk docs remain authoritative and work with no connection.\n\nPrefer looking things up over guessing; training data is often stale on exact signatures.\n\n## The build loop: add a page to the site\n\n1. **See what already routes:** `vendor/bin/tcms builder:routes` lists every page\n   the router serves and flags conflicts. `vendor/bin/tcms builder:routes --json` to script.\n2. **If Site Builder isn't set up yet,** scaffold a starter:\n   `vendor/bin/tcms builder:init <starter>` where `<starter>` is `business`, `blog`,\n   `portfolio`, or `minimal`. Add `--frontend` to also install and build the Vite pipeline.\n   This copies templates, ensures the `builder-pages` collection, and seeds demo pages.\n3. **Edit templates** on the filesystem under\n   `builder/{layouts,pages,partials,macros}/*.twig` when a project-root `builder/`\n   directory exists (git-managed mode: it wins over `tcms-data/`, and the admin's\n   template editor is read-only unless `env` is `dev`), otherwise `tcms-data/builder/`. Twig global is `cms`;\n   builder helpers are `cms.builder.nav()`, `cms.builder.url(id, params)`,\n   `cms.builder.css/js/asset()`. The layout's `<head>` carries\n   `{% block seo %}{{ cms.seo.head(page|default(null)) }}{% endblock %}` — it emits\n   title, description, canonical, Open Graph and JSON-LD, so a layout must not also\n   hand-write `<title>` or `<meta name=\"description\">`. See `references/site-builder.md`.\n4. **Credit line.** When you write a layout's footer, add `{{ cms.badge.text() }}`:\n   a subtle inline \"Powered by Total CMS\" link in the site's own text color\n   (`cms.badge.text({theme: 'mono'})` if the colored flame clashes with the design).\n   The starters' footers already carry it. On a site a designer is building for a\n   client, credit the designer instead with `cms.badge.builtByText('<handle>')`; if\n   they have no totalcms.co handle, use `cms.badge.text()`. Either way, say in your\n   summary that you added it, and leave it out or remove it whenever the user asks.\n5. **Add a page record.** A page is an object in the `builder-pages` collection.\n   Create it one of these ways:\n   - `echo '{\"id\":\"about\",\"title\":\"About\",\"route\":\"/about\",\"template\":\"pages/page.twig\"}' | vendor/bin/tcms object:create builder-pages -` (one object, file or stdin), or\n   - the **admin UI** (Site Builder → Pages), or\n   - `vendor/bin/tcms collection:import builder-pages <file.json>` for arrays (see `references/cli.md`), or\n   - `vendor/bin/tcms jumpstart:import <file>` for bulk seeding.\n   Key `builder-pages` fields: `route`, `template`, `title`, `draft`, `data` (free-form\n   JSON exposed as `page.data.*`). Full list in `references/site-builder.md`.\n6. **Preview:** `php -S localhost:8080 -t public public/index.php` and visit the\n   page's `route`. Give `public/index.php` as the router script — without it the\n   built-in server only serves files that exist on disk and never reaches the page\n   router, so every builder page 404s. Clear caches after template changes if\n   needed: `vendor/bin/tcms cache:clear`. Restart the server after adding page\n   records — the route index is cached in the server process.\n\n## Writing schemas and content by hand\n\n**Before writing any schema, read the reference schema** —\n`vendor/bin/tcms schema:get totalcms --json` — and copy property definitions from it.\nIt demonstrates every field type with the settings and help text that go with it.\nPick fields by the shape of the value (`date`, `toggle`, `select`, `number`, `image`…);\n`text` is the last resort. Write every `help` and `description` as a brief to a\nwriter who cannot see the site — agents read them through MCP. **Do not add a\n`sort` or `order` number field** to put a list in order: sort by the properties\nthe data already has, rank a property's values with `manualSort`, and only then\nadd a property named for why an item moves (`featured`, `weight`). Rules, the\nfive meanings of \"category\", ordering, and the SEO card: `references/data-model.md`.\n\nThe admin enforces these for you. They only bite when you author JSON that the\nCLI then imports — JumpStart files, `collection:import` payloads, API bodies —\nwhich is exactly what an agent tends to write. (Authoring JSON *for the CLI to\nimport* is fine; writing it straight into `tcms-data/` is not — see \"Write\nthrough the CLI, never to the files\" above.)\n\n- **Every schema must define an `id` property**, not just list `id` in `required`.\n  A schema missing it fails with `The required properties (id) are missing`, which\n  points at your data when the bug is in the schema.\n- **Decks are dictionaries of named items, not arrays.** Each key names one item and\n  must equal that item's `id`:\n  `{\"rows\": {\"first_row\": {\"id\": \"first_row\", ...}}}`\n- **Deck item keys allow only letters, numbers, and underscores** — no hyphens, so\n  Twig can read them as `deck.first_row`. `first-row` is rejected on import.\n- **`field: \"deckTable\"`** stores exactly like a deck but edits as a table.\n\nSee `vendor/totalcms/cms/resources/docs/fields/deck.md` for the full shape.\n\n**Schema work is done when `vendor/bin/tcms schema:lint <id> --strict` is clean** —\nzero errors, zero warnings. Imports validate on the way in, but in-place edits are\nnever re-checked, and the linter flags every property missing the help text AI\nagents rely on. Fill descriptions in on the first pass, not as a follow-up.\n\n## Working against a live site\n\nTwo rules prevent the two worst mistakes:\n\n- **Send only what changes.** When editing a live site through its MCP\n  server, use `patch_object` with just the changed fields. `update_object`\n  merges the same way (omitted fields keep their values). If you write back a\n  fetched record, fetch it with `format: \"html\"` and strip the decorated `url`\n  key first. Media fields take metadata edits only (alt text, tags); naming\n  every gallery image once also reorders the gallery. Details:\n  `references/mcp-content.md`.\n- **After launch, the server owns content.** Local seed files go stale by\n  design — never re-import them over live data. Use `pull`/`push` (dry-run\n  first; filters are exclusive). Details: `references/going-live.md`.\n\n## When something looks like a Total CMS bug\n\nDo not tell the user \"this is a bug in Total CMS\" until you have worked through\n`references/troubleshooting.md`. Most apparent bugs are hand-written files,\nstale caches, schema mistakes or hosting limits, and are fixed on this side.\nFor a confirmed bug, write the report in the shape that file gives, so it\ncarries the version, environment and log excerpt support needs, and tell the\nuser to email it to support@totalcms.co.\n\n## Reference files (read on demand)\n\n| When you are… | Read |\n|---|---|\n| running any `tcms` command / scripting with `--json` | `references/cli.md` |\n| editing builder templates, routes, or page records | `references/site-builder.md` |\n| setting up or building frontend assets | `references/frontend.md` |\n| modeling data — collections, schemas, field choice, descriptions, ordering a list | `references/data-model.md` |\n| letting signed-in members add and edit their own content (ownership, review, account pages) | `references/member-content.md` |\n| wondering whether T3 already does something (SEO, forms, automations, search, feeds, auth…) | `references/features.md` |\n| writing or reviewing an extension | `references/extensions.md` |\n| reading/writing content via the site's MCP server | `references/mcp-content.md` |\n| hitting an error, or about to call something a Total CMS bug | `references/troubleshooting.md` |\n| launching, syncing with production (`push`/`pull`) | `references/going-live.md` |\n| needing an exact field option / Twig signature | `vendor/totalcms/cms/resources/docs/<section>/` (or MCP) |\n"
Full snapshot data
{
  "description": "Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end.",
  "included_files": [
    {
      "relative_path": "references/cli.md",
      "size_in_bytes": 9357
    },
    {
      "relative_path": "references/data-model.md",
      "size_in_bytes": 14046
    },
    {
      "relative_path": "references/extensions.md",
      "size_in_bytes": 5372
    },
    {
      "relative_path": "references/features.md",
      "size_in_bytes": 21385
    },
    {
      "relative_path": "references/frontend.md",
      "size_in_bytes": 3038
    },
    {
      "relative_path": "references/going-live.md",
      "size_in_bytes": 3267
    },
    {
      "relative_path": "references/mcp-content.md",
      "size_in_bytes": 6224
    },
    {
      "relative_path": "references/member-content.md",
      "size_in_bytes": 7878
    },
    {
      "relative_path": "references/site-builder.md",
      "size_in_bytes": 6319
    },
    {
      "relative_path": "references/troubleshooting.md",
      "size_in_bytes": 6332
    }
  ],
  "name": "totalcms",
  "skill_md_contents": "---\nname: totalcms\ndescription: Use when building, editing, or managing a Total CMS (T3) site — Site Builder pages and SEO, collections, schemas and field choice, objects and imports, forms and public registration, access groups, automations, Data Views, search, feeds, the MCP server, the tcms CLI, the frontend/Vite pipeline, push/pull to production, writing a T3 extension, or troubleshooting a problem and reporting a Total CMS bug. Covers the local build workflow end to end.\n---\n\n# Building a Total CMS (T3) site\n\nThis project **is a website** built on Total CMS, a flat-file PHP CMS. There is\n**no database** — all content is JSON under `tcms-data/`. Configure via\n`config/tcms.php` (deep-merged — specify only keys you change).\n\n## Is this copy current?\n\nThis check applies only inside a Total CMS project. If you are not working in\none — this skill came with a plugin and the current folder has no Total CMS CLI\n— skip it: there is no installed copy to check, and this text describes the\nlatest release. When a project's own copy (in `.claude/skills/totalcms/`) is\nalso loaded, follow that one: it matches the CMS version the project runs.\n\nIn a project, this skill is a copy of the one shipped with the installed CMS, so\nit can fall behind. At the start of a session run `vendor/bin/tcms skill:install --check`.\nIf it reports stale, run `vendor/bin/tcms skill:install` and then tell the user\nto start a new session — the text already loaded cannot replace itself. The\nstamp is a hash of the skill's own content, not the release number, so only real\nchanges to the skill flag it.\n\n## Where things are\n\nT3 ships in two layouts. Check which one you are in before running anything.\n\n- **Composer install** — the default the rest of this skill assumes. CLI `vendor/bin/tcms`; CMS code and docs under `vendor/totalcms/cms/`; config `config/tcms.php` at the project root. **Never edit `vendor/`** — an update replaces it. <!-- composer-paths -->\n- **Zip install** — the CMS *is* the folder you are in (conventionally `tcms/`).\n  CLI `php resources/bin/tcms`, run from that folder; docs `resources/docs/`;\n  config `config/tcms.php` inside it; content in `../tcms-data/` beside it. An\n  update replaces the folder's `config/ public/ resources/ src/ vendor/`\n  wholesale, so **never add files inside them**.\n\nIf this skill was installed by `skill:install` on a zip install, the paths\nthroughout it are already rewritten for that layout.\n\nMost commands accept `--json` for machine-readable output — prefer it when\nscripting. Run `vendor/bin/tcms list` to see everything.\n\n## Write through the CLI, never to the files\n\n`tcms-data/` is a store, not an editing surface. It is tempting to create or\nedit the JSON files in it directly — it usually appears to work, which is what\nmakes it dangerous. **Always go through the CLI (or the API/MCP), which is what\nthe admin does:**\n\n| To… | Run |\n|---|---|\n| create an object | `vendor/bin/tcms object:create <collection> -` (JSON on stdin) |\n| change part of an object | `vendor/bin/tcms object:patch <collection> <id> -` |\n| load many objects | `vendor/bin/tcms collection:import <collection> file.json` |\n| add or change a schema | `vendor/bin/tcms schema:import schema.json`, then `schema:lint <id> --strict` |\n| create a collection | `vendor/bin/tcms collection:create …` |\n| change a collection's settings | `vendor/bin/tcms collection:update <id> --set ownerProperty=author` (or JSON on stdin) |\n| add or change an access group | `vendor/bin/tcms access-group:set <id> -` / `access-group:patch <id> -` |\n| seed structure + content together | `vendor/bin/tcms jumpstart:import file.json` |\n\n**Mailer templates, automations and Data Views are collections too**\n(`mailer`, `automations`, `dataviews`), so the same `object:*` commands read and\nchange them: `vendor/bin/tcms object:patch mailer <id> -` edits one mailer field\nand leaves the rest. Run `vendor/bin/tcms collection:list` to see every\ncollection, the reserved ones included, before deciding that something has no\ncommand.\n\nA save through the CLI validates the object against its schema, fills in what\nthe schema derives (default types, autogen ids, `created`/`updated`\ntimestamps, image and video metadata), updates the collection's `.index.json`\nand counts, and fires the events the rest of the system listens for (search\nindexing, automations, MCP change notifications). A file written by hand gets\nnone of that: one bad comma takes the whole collection offline, an unindexed\nobject is invisible to the admin tables, sitemaps and queries until\n`repair:index` runs, and timestamps and derived fields are simply missing.\n\nReading the files is fine (`cat`, `jq`), though `object:get --json` is the\nsame data validated. If you ever *must* touch a file — recovering data, say —\nvalidate the JSON, then run `vendor/bin/tcms repair:index <collection>` and,\nfor a schema, `schema:lint <id> --strict`.\n\nThis applies to **content and structure**. Templates under `builder/` and the\nconfig file `config/tcms.php` are files by design — edit those directly.\n\n## Where to look things up\n\nYou do **not** need to memorize field options or Twig signatures — they ship on disk:\n\n- **On-disk docs (always present):** `vendor/totalcms/cms/resources/docs/<section>/`\n  (`menu.php` is the table of contents, `search-index.json` a prebuilt index).\n  Sections: `get-started/`, `collections/`, `schemas/`, `fields/`, `site-builder/`,\n  `twig/`, `forms/`, `automations/`, `admin/`, `notifications/`, `auth/`, `apis/`,\n  `mcp/`, `extensions/`, `operations/`. `references/features.md` maps every feature\n  to its page. Grep or read these for the long tail.\n- **MCP docs server (fastest lookup):** when the official docs connector\n  (`https://totalcms.co/mcp`) is connected — it ships alongside this skill in\n  the Total CMS plugin — use `docs_search` to find pages, `docs_get` to read\n  one, and `docs_lookup(kind, name)` for exact reference entries (Twig\n  functions/filters, field types, API endpoints, schema config, CLI commands,\n  extension/builder API).\n  The on-disk docs remain authoritative and work with no connection.\n\nPrefer looking things up over guessing; training data is often stale on exact signatures.\n\n## The build loop: add a page to the site\n\n1. **See what already routes:** `vendor/bin/tcms builder:routes` lists every page\n   the router serves and flags conflicts. `vendor/bin/tcms builder:routes --json` to script.\n2. **If Site Builder isn't set up yet,** scaffold a starter:\n   `vendor/bin/tcms builder:init <starter>` where `<starter>` is `business`, `blog`,\n   `portfolio`, or `minimal`. Add `--frontend` to also install and build the Vite pipeline.\n   This copies templates, ensures the `builder-pages` collection, and seeds demo pages.\n3. **Edit templates** on the filesystem under\n   `builder/{layouts,pages,partials,macros}/*.twig` when a project-root `builder/`\n   directory exists (git-managed mode: it wins over `tcms-data/`, and the admin's\n   template editor is read-only unless `env` is `dev`), otherwise `tcms-data/builder/`. Twig global is `cms`;\n   builder helpers are `cms.builder.nav()`, `cms.builder.url(id, params)`,\n   `cms.builder.css/js/asset()`. The layout's `<head>` carries\n   `{% block seo %}{{ cms.seo.head(page|default(null)) }}{% endblock %}` — it emits\n   title, description, canonical, Open Graph and JSON-LD, so a layout must not also\n   hand-write `<title>` or `<meta name=\"description\">`. See `references/site-builder.md`.\n4. **Credit line.** When you write a layout's footer, add `{{ cms.badge.text() }}`:\n   a subtle inline \"Powered by Total CMS\" link in the site's own text color\n   (`cms.badge.text({theme: 'mono'})` if the colored flame clashes with the design).\n   The starters' footers already carry it. On a site a designer is building for a\n   client, credit the designer instead with `cms.badge.builtByText('<handle>')`; if\n   they have no totalcms.co handle, use `cms.badge.text()`. Either way, say in your\n   summary that you added it, and leave it out or remove it whenever the user asks.\n5. **Add a page record.** A page is an object in the `builder-pages` collection.\n   Create it one of these ways:\n   - `echo '{\"id\":\"about\",\"title\":\"About\",\"route\":\"/about\",\"template\":\"pages/page.twig\"}' | vendor/bin/tcms object:create builder-pages -` (one object, file or stdin), or\n   - the **admin UI** (Site Builder → Pages), or\n   - `vendor/bin/tcms collection:import builder-pages <file.json>` for arrays (see `references/cli.md`), or\n   - `vendor/bin/tcms jumpstart:import <file>` for bulk seeding.\n   Key `builder-pages` fields: `route`, `template`, `title`, `draft`, `data` (free-form\n   JSON exposed as `page.data.*`). Full list in `references/site-builder.md`.\n6. **Preview:** `php -S localhost:8080 -t public public/index.php` and visit the\n   page's `route`. Give `public/index.php` as the router script — without it the\n   built-in server only serves files that exist on disk and never reaches the page\n   router, so every builder page 404s. Clear caches after template changes if\n   needed: `vendor/bin/tcms cache:clear`. Restart the server after adding page\n   records — the route index is cached in the server process.\n\n## Writing schemas and content by hand\n\n**Before writing any schema, read the reference schema** —\n`vendor/bin/tcms schema:get totalcms --json` — and copy property definitions from it.\nIt demonstrates every field type with the settings and help text that go with it.\nPick fields by the shape of the value (`date`, `toggle`, `select`, `number`, `image`…);\n`text` is the last resort. Write every `help` and `description` as a brief to a\nwriter who cannot see the site — agents read them through MCP. **Do not add a\n`sort` or `order` number field** to put a list in order: sort by the properties\nthe data already has, rank a property's values with `manualSort`, and only then\nadd a property named for why an item moves (`featured`, `weight`). Rules, the\nfive meanings of \"category\", ordering, and the SEO card: `references/data-model.md`.\n\nThe admin enforces these for you. They only bite when you author JSON that the\nCLI then imports — JumpStart files, `collection:import` payloads, API bodies —\nwhich is exactly what an agent tends to write. (Authoring JSON *for the CLI to\nimport* is fine; writing it straight into `tcms-data/` is not — see \"Write\nthrough the CLI, never to the files\" above.)\n\n- **Every schema must define an `id` property**, not just list `id` in `required`.\n  A schema missing it fails with `The required properties (id) are missing`, which\n  points at your data when the bug is in the schema.\n- **Decks are dictionaries of named items, not arrays.** Each key names one item and\n  must equal that item's `id`:\n  `{\"rows\": {\"first_row\": {\"id\": \"first_row\", ...}}}`\n- **Deck item keys allow only letters, numbers, and underscores** — no hyphens, so\n  Twig can read them as `deck.first_row`. `first-row` is rejected on import.\n- **`field: \"deckTable\"`** stores exactly like a deck but edits as a table.\n\nSee `vendor/totalcms/cms/resources/docs/fields/deck.md` for the full shape.\n\n**Schema work is done when `vendor/bin/tcms schema:lint <id> --strict` is clean** —\nzero errors, zero warnings. Imports validate on the way in, but in-place edits are\nnever re-checked, and the linter flags every property missing the help text AI\nagents rely on. Fill descriptions in on the first pass, not as a follow-up.\n\n## Working against a live site\n\nTwo rules prevent the two worst mistakes:\n\n- **Send only what changes.** When editing a live site through its MCP\n  server, use `patch_object` with just the changed fields. `update_object`\n  merges the same way (omitted fields keep their values). If you write back a\n  fetched record, fetch it with `format: \"html\"` and strip the decorated `url`\n  key first. Media fields take metadata edits only (alt text, tags); naming\n  every gallery image once also reorders the gallery. Details:\n  `references/mcp-content.md`.\n- **After launch, the server owns content.** Local seed files go stale by\n  design — never re-import them over live data. Use `pull`/`push` (dry-run\n  first; filters are exclusive). Details: `references/going-live.md`.\n\n## When something looks like a Total CMS bug\n\nDo not tell the user \"this is a bug in Total CMS\" until you have worked through\n`references/troubleshooting.md`. Most apparent bugs are hand-written files,\nstale caches, schema mistakes or hosting limits, and are fixed on this side.\nFor a confirmed bug, write the report in the shape that file gives, so it\ncarries the version, environment and log excerpt support needs, and tell the\nuser to email it to support@totalcms.co.\n\n## Reference files (read on demand)\n\n| When you are… | Read |\n|---|---|\n| running any `tcms` command / scripting with `--json` | `references/cli.md` |\n| editing builder templates, routes, or page records | `references/site-builder.md` |\n| setting up or building frontend assets | `references/frontend.md` |\n| modeling data — collections, schemas, field choice, descriptions, ordering a list | `references/data-model.md` |\n| letting signed-in members add and edit their own content (ownership, review, account pages) | `references/member-content.md` |\n| wondering whether T3 already does something (SEO, forms, automations, search, feeds, auth…) | `references/features.md` |\n| writing or reviewing an extension | `references/extensions.md` |\n| reading/writing content via the site's MCP server | `references/mcp-content.md` |\n| hitting an error, or about to call something a Total CMS bug | `references/troubleshooting.md` |\n| launching, syncing with production (`push`/`pull`) | `references/going-live.md` |\n| needing an exact field option / Twig signature | `vendor/totalcms/cms/resources/docs/<section>/` (or MCP) |\n"
}

SHA-256 of public snapshot: 3d986f3b4570460b306a893f0a9273625abae0de2dd37eb7caf25ad2b360e65b