Adapto schema apply
Skill adaptocms/adapto-cms-agent-skills/plugin/skills/adapto-schema-apply
A pack of skills for AI coding agents (Claude Code, Cursor) that lets them operate Adapto CMS end-to-end: scaffold projects, design schemas, seed content, translate, run SEO, audit content, roll back.
npx -y skills add adaptocms/adapto-cms-agent-skills --skill adapto-schema-applyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Apply an approved .adapto/schema-plan.json to the CMS — create Article categories and custom collections (with a two-pass step for references), idempotently, via the adapto CLI. Plan-then-apply; writes content. Pairs with adapto:schema-design.
SKILL.md
9.2 KB, as published. Nobody here has run it
adapto:schema-apply
The gated writer of the schema pair. It reads .adapto/schema-plan.json (produced by
adapto:schema-design) and creates the Article categories and custom collections it describes via
the adapto CLI. It is idempotent and re-runnable — existing collections/categories are reused or
updated, never duplicated.
When to use
- After
adapto:schema-designproduced (and you've eyeballed or hand-edited).adapto/schema-plan.json, and you're ready to create those collections + categories in Adapto. - Triggers: "apply the schema", "create the collections", "build my schema in Adapto".
When not to use
- No plan file yet → run
adapto:schema-designfirst. - Seeding content rows into the collections →
adapto:content-seed.
Inputs
.adapto/schema-plan.json— the approved plan (collections, categories, language). Missing/invalid → stop and route toadapto:schema-design.- The working tenant — confirm it explicitly; never assume the saved/active one. With 2+ tenants, have the user pick; with one, state it and proceed.
Outputs
- The plan's Article categories and custom collections created (or updated) in the CMS,
draftunless the plan says otherwise. - The reserved
_adapto_seocollection ensured (the CMS home for per-piece SEO metadata — reserved-slugs.md), soadapto:content-uploadcan write metadata. - A realized
.adapto/schema.json— a{"<slug>": "<id>", …}map of every collection's slug to its CMS id (incl._adapto_seo) — foradapto:content-upload(andadapto:content-seed) to target. - A report: which collections/categories were created vs reused, with ids.
- Next step: suggest
adapto:content-researchto start a content cycle (research → plan → create → upload), oradapto:content-seedfor a quick set of starter drafts. Both read.adapto/schema.json.
Preconditions
- Preflight with the
adapto:doctorchecks. - Hard-block on an authenticated CLI (
adapto auth me) and a selected tenant — this skill writes. .adapto/schema-plan.jsonmust exist (else route toadapto:schema-design).adaptoCLI>= 0.1.3.
Plan phase
Read and validate .adapto/schema-plan.json, then print a machine-parseable plan and wait for an explicit
approve:
- For each category and collection: whether it will be created or reused (resolved live via
get-by-slug), plus its fields, the target language, anddraftstatus. - The realized
.adapto/schema.jsonit will write. - That the reserved
_adapto_seocollection will be ensured (created if absent) for content metadata. - No cost/token figures. If the plan is empty, say so and stop — nothing to apply.
Validate before proposing: every field type is in the safe vocabulary (cheatsheet §5), and every
reference field's related_collection slug exists in the plan. Surface any problem here, before writing.
Apply phase
Runs only after approval. Deterministic CLI calls — --json on every one.
-
Validate the plan before the first write. Server-side rejections are per-request, so a bad field in collection #3 still leaves collections #1–2 and every category already created — a partial apply. Catching it locally costs nothing and keeps the run all-or-nothing. Check each field:
typeis in the vocabulary (text, textarea, rich_text, number, date, date_range, boolean, select, multi_select, reference, image, file, url, email, color).multiple: trueonly ontext, textarea, number, date, select, reference, image, file, url, email, color. Onmulti_select,boolean,rich_text, ordate_rangethe server returnsBad request: Field <name> of type <type> cannot be multipleand the run dies mid-way.multi_selectis already multi-valued — drop themultiplekey rather than adding it.referencefields name arelated_collectionthat exists in the plan or the CMS. On a violation: stop before writing anything, show the offending field, and offer the fix (dropmultiple, or switchmulti_select→select+multiple: true).
-
Resolve language. Use the plan's
languageif the tenant has it enabled; otherwise fall back to the tenant's first enabled code and note the substitution. Discover with:adapto auth orgs --json -
Categories — idempotent (no
--statusflag on categories):adapto categories get-by-slug <slug> --json # reuse the id on a hit adapto categories create --name "<name>" --slug <slug> --language <lang> [--description "<desc>"] --json -
Collections — TWO PASS (robust even to circular references):
- Pass 1 — create each collection with its non-reference fields only; capture each
slug → id. On aget-by-slughit, reuse the id (andupdateif fields differ):adapto collections get-by-slug <slug> --json adapto collections create --name "<name>" --slug <slug> \ --description "<desc>" --language <lang> --status <status> \ --fields-json '<fields WITHOUT type:reference entries>' --json - Pass 2 — add the
referencefields now that their targets exist, resolving eachrelated_collectionslug → the real id captured in Pass 1:adapto collections update <id> --fields-json '<full fields incl. resolved reference ids>' --json
- Pass 1 — create each collection with its non-reference fields only; capture each
3b. Ensure the reserved _adapto_seo collection (idempotent) — the CMS home for per-piece SEO metadata
that adapto:content-upload writes and adapto:seo-wire reads (reserved-slugs.md):
adapto collections get-by-slug _adapto_seo --json # reuse the id on a hit
adapto collections create --name "Adapto SEO" --slug _adapto_seo \
--description "Per-piece SEO metadata for Adapto content" --language <lang> --status draft \
--fields-json '<the _adapto_seo field-set — reserved-slugs.md>' --json
⚠️ Reserved-slug fallback: if _adapto_ is rejected, retry once with adapto-seo; record which slug
worked. Capture its id into .adapto/schema.json alongside the user collections.
4. Report + persist. Print created-vs-reused with ids, then write .adapto/schema.json as
{"<slug>": "<id>", …} (incl. _adapto_seo) for adapto:content-upload. Loop cleanly — judge success from each call's --json,
not the shell exit code, and make the loop/function exit 0 on success so a created batch never surfaces as a
red Error: Exit code 1 (conventions.md §8). Then restart the dev server (stop→start) and keep it running so
the new collections/categories appear — never kill it (starters sync content at startup — conventions §14).
--fields-json is a FieldDefinitionModel[]. No --source — collections and categories carry no provenance.
Errors and recovery
- A create fails mid-run (partial state) → whatever was created before the failure stays. This is safe:
every step is
get-by-slug-first, so a re-run reuses those ids instead of duplicating. Report what landed, fix the offending field inschema-plan.json, and re-run. Step 0 exists so this rarely happens. Field <name> of type <type> cannot be multiple→multiple: trueon a type that forbids it (usuallymulti_select). Drop the key or useselect+multiple: true, then re-run.- Plan missing/invalid → stop; tell the user to run
adapto:schema-design. - Server rejects a field
type→ surface which collection/field, and suggest a safe-vocabulary type (cheatsheet §5); don't retry blindly. - A
reference'srelated_collectionslug isn't in the plan → stop before writing; the plan is inconsistent. - Collection/category already exists → reuse/update via
get-by-slug; never create a duplicate. - Partial failure mid-apply (collections have no batch — they're per-call) → report what was created so far, then stop. Re-running is safe (idempotent).
- Not authenticated / no tenant → stop; offer both auth paths —
Log inorRegister(conventions §11) — then tenant selection. - Language discovery fails → ask the user for a language code the tenant has enabled; don't guess.
Forbidden actions
- Never write without an approved plan (plan-then-apply).
- Never pass
--sourcehere — collections/categories have no provenance field. - Never create built-in Articles/Pages — the plan's
advisorymap is documentation only. - Never assume the working tenant — confirm it before any write.
- Never modify the scaffolded read-client (forbidden-actions.md).