From agent-skills
Migrates an existing SSG site to CloudCannon. Use when onboarding a site to CloudCannon, adding CMS support, or making a template CloudCannon-compatible.
How this skill is triggered — by the user, by Claude, or both
Slash command
/agent-skills:migrating-to-cloudcannonThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill orchestrates a full migration of an existing SSG site to CloudCannon. It coordinates five phases, delegating domain-specific work to standalone skills that can also be used independently.
This skill orchestrates a full migration of an existing SSG site to CloudCannon. It coordinates five phases, delegating domain-specific work to standalone skills that can also be used independently.
Model recommendation: Migrations involve multi-file architectural decisions across five phases. Use a high-reasoning model (not a fast/lightweight one) for best results.
| SSG | Guide |
|---|---|
| Astro | astro/overview.md |
If the site is being generated as part of this task (e.g. converting from WordPress), read astro/cc-friendly-conventions.md before scaffolding — it covers the structural choices that make the migration smooth. Once scaffolded, return here and run the migration phases.
Run from the project root:
npx @cloudcannon/cli configure detect-ssg
Use the detected SSG to pick the correct guide above.
Each SSG guide walks through these in order. Phases that delegate to standalone skills are marked below.
cloudcannon-configuration skill.cloudcannon-snippets skill.cloudcannon-visual-editing skill.Not every site needs all phases. Small sites may skip Phase 3 if content is already well-structured. Phase 4 is optional but high-value.
For each phase, in order:
in_progress before starting it; mark completed only when the checklist item is satisfied. Do not batch-complete tasks at the end of the phase..cloudcannon/migration/<phase>.md documenting decisions, findings, and anything the user should review.Why: checklists catch things agents otherwise skim past — data collections missing from collections_config, data_config entries missing for referenced data files, blog/detail page editables skipped while focusing on page-builder blocks, arrays not linked to structures. TaskCreate makes the skim visible.
These rows define what must be true for a phase to be safely picked up by a fresh conversation. They are not walls inside one conversation — cross-phase fixes (per step 3 above) are still fine. They exist so a chunked migration's later runs have a clean starting point.
| After phase | Ready for handoff when… |
|---|---|
| 1. Audit | .cloudcannon/migration/audit.md exists, contains the census table, and lists every collection + every page route. Sectioning thresholds (below) have been evaluated; if tripped, .cloudcannon/migration/plan.md exists. |
| 2. Configuration | cloudcannon.config.yml validates against the published JSON schema (no IDE red squigglies). Every collection in the audit has a collections_config entry; every referenced data file has a data_config entry. .cloudcannon/migration/configuration.md written. |
| 3. Content | All structural content changes from Phase 2 are reflected in the files. npm run build (or project equivalent) succeeds. .cloudcannon/migration/content.md written. |
| 4. Visual editing | Every section flagged in the audit census as "needs editable region" has been wired or has a documented justification for not being wired. registerComponents.ts registers every component used inside a wrapped section. .cloudcannon/migration/visual-editing.md written. |
| 5. Build and test | Production build succeeds locally. User has run their CloudCannon-side verification (preview, inline edit, save-to-git). .cloudcannon/migration/build.md written. |
Migrations can run end-to-end in one conversation, but on larger sites context fills up — quality drops in later phases (especially Phase 4 visual editing) when the agent is recalling decisions from earlier phases through a long backscroll. Chunking into fresh conversations is a way to avoid that.
Chunking is a suggestion, not a wall. The agent doesn't halt between phases — it tells the user "context is heavy; consider opening a fresh conversation for Phase N" and lets the user choose. If the user keeps going in the same conversation, that's fine.
At the end of Phase 1, evaluate the sizing thresholds against .cloudcannon/migration/audit.md:
| Signal | Threshold | Source |
|---|---|---|
| Total pages | > 30 | Audit § Pages and routing |
Hardcoded .astro → YAML conversions | > 15 | Audit census table rows recommending page-builder or fixed-schema collection |
| Distinct collections | > 5 | Audit § Content collections + new collections from census |
If any 2 thresholds are tripped, write .cloudcannon/migration/plan.md using the template below, then suggest to the user that later phases run in fresh conversations. Phase 4 (visual editing) is the most context-hungry — it's the most likely candidate for a fresh start.
| Shape | When |
|---|---|
| Vertical (per-collection) | Page-builder pages or unique-shape collections dominate — each unit has its own schema/visual-editing decisions |
| Horizontal (per-phase) | Collections are mostly uniform — repetitive per-collection work benefits from one mental model at a time |
.cloudcannon/migration/plan.md template# Migration plan
## Sizing
- Total pages: <n> (threshold >30: <tripped|ok>)
- Hardcoded → YAML conversions: <n> (threshold >15: <tripped|ok>)
- Distinct collections: <n> (threshold >5: <tripped|ok>)
- Tripped: <count>/3 → <chunked recommended|single-pass fine>
## Shape (if chunking)
<vertical|horizontal> — because: <one-line reason>
## Chunks
Each chunk is intended as a single agent run, ideally in a fresh conversation
once context is heavy. The agent reads `.cloudcannon/migration/audit.md` + this file + the
listed phase doc, then works the listed scope.
| # | Scope | Phase(s) | Inputs | Output artefact |
| --- | -------------------------------- | -------- | -------------------------- | ----------------------------------------- |
| 1 | <e.g. all collections — config> | 2 | audit.md | cloudcannon.config.yml + configuration.md |
| 2 | <e.g. blog collection — content> | 3 | audit.md, configuration.md | content.md (blog section) |
| 3 | <...> | ... | ... | ... |
## Global decisions locked in chunk 1 (do not revisit)
- Collection URL patterns
- Shared structures (`_structures`)
- Snippet configs (if MDX/inline HTML)
- `registerComponents.ts` setup
Resumption brief (paste into a fresh conversation): "Read .cloudcannon/migration/audit.md, .cloudcannon/migration/plan.md, and the phase doc(s) listed for chunk N. Work chunk N's scope. Write the output artefact and stop."
Repetition → script rule: After migrating 2 entries of the same shape, write a throwaway script for the rest. 23 hand-conversions of the same article shape is wasted tokens and an error multiplier.
Deterministic migration steps are automated as scripts in scripts/. Run these before or during the relevant phase.
All written to .cloudcannon/migration/ (under .cloudcannon/ so the CLI doesn't detect the folder as a collection): one file per phase (audit.md, configuration.md, content.md, visual-editing.md, build.md), plus plan.md if the migration is sectioned. See the per-phase workflow above for the gates that consume each file.
| Check | Owner |
|---|---|
Local build (npm run build or whatever package.json defines) | Agent |
Builds, greps, small scripts, dist/ inspection | Agent |
| Fidelity checks in CloudCannon (preview, inline edit, save-to-git) | Human |
Prefer asking the user to run CloudCannon verification over spinning up long-lived dev servers or heavy end-to-end testing in the agent session.
Close after a meaningful chunk, not every tiny edit. At minimum: when Phase 5 (Build and test) is done for a first full migration pass. If the user stops earlier (e.g. after configuration only), hand off at that milestone instead.
Be direct and brief:
Skip empty phrases ("let me know if you need anything"). Thanking them once for checking is fine.
@file, shared partials) update the intended source fileConcrete signals: the exact command run, CloudCannon build log snippets if the remote build failed, the page URL and what they clicked if the editor misbehaved, or a short description of what differs from expected.
End with one line that invites the next pass — when they've run those checks, reply with any failures or odd behavior.
Follow existing project conventions when present. Otherwise:
kebab-case for filescamelCase for JavaScript and JSONsnake_caseFor specific architectural decisions and config-syntax mistakes, see:
| Topic | Owner |
|---|---|
| Classifying static pages (source-editable vs page-builder vs collection) | astro/audit.md § Classifying static pages |
home.md vs index.md, collection-of-one | astro/page-building.md § Common mistakes |
| Shared UI (CTA banners, footers, share blocks) | astro/cc-friendly-conventions.md § Shared-UI treatment table |
Multi-schema collections (pages with z.union) | ../cloudcannon-configuration/astro/configuration.md § Schemas |
| Config-syntax hallucinations (wrong keys/types) | cloudcannon-configuration § Common invalid keys |
Markdown body renders as unstyled text — no heading sizes, list bullets, or link colour — despite prose prose-lg classes | @tailwindcss/typography not installed or not registered. Tailwind 4 needs @plugin "@tailwindcss/typography"; in the main CSS (after @import "tailwindcss";). Two-line fix: npm install @tailwindcss/typography + add the @plugin directive. |
| Excuse | Reality |
|---|---|
| "This site is simple enough to skip the audit" | The audit catches structural issues early. Skipping it means discovering problems mid-configuration. |
| "I'll do the checklist at the end" | Read checklists BEFORE starting each phase. They tell you what to aim for. |
| "Content restructuring can wait" | If a missing field blocks configuration, add it now. Phases are sequential, not siloed. |
| "Visual editing is optional so I'll skip it" | It's the highest-value phase for editors. Only skip if the user explicitly says so. |
| "The build passes so we're done" | A passing build doesn't mean the editor works. The user must verify in CloudCannon. |
"I'll call the homepage file home.md — it's more descriptive" | CloudCannon resolves the URL from the slug; home.md with url: "/[slug]/" → /home/. Use index.md so Astro collapses the slug to /. |
| "It's hardcoded, so it's developer-only" | If an editor can see it on the page, they must be able to edit it. The mechanism depends on the page: shared UI (CTA banners, footers, share blocks, author cards) → data file; unique-layout pages with 2+ sections → page-builder pages collection entry; long-form prose page → fixed-schema collection with markdown body. data-editable="source" is for long-form prose only — not the default for any one-off string. See astro/cc-friendly-conventions.md § Shared-UI treatment table and astro/page-building.md § When to reach for page builder. |
| "This page is unique so it should be source-editable" | Unique-layout pages with 2+ sections belong in a pages collection with a page-builder schema. Source-editable is for long-form prose only. See astro/audit.md § Classifying static pages. |
"I'll make a single-entry homepage collection" | Use one pages collection with index.md as one entry. Add our-team.md, about.md, etc. as more entries. CloudCannon collections support multiple schemas per collection — both via schemas: config and via Zod z.union in Astro content config. See ../cloudcannon-configuration/astro/configuration.md § Schemas. |
| "Page builder is overkill for these few pages" | Page builder is the default for any site with more than one unique-layout page. The cost is a [...slug].astro catch-all + a BlockRenderer — both are mechanical. The benefit is editors can add new pages without engineering. |
Creates, edits, and verifies skills using a test-driven development approach with pressure scenarios and subagents.
npx claudepluginhub cloudcannon/agent-skills --plugin agent-skills