| name | statamic-addon-v5-to-v6 |
|---|---|
| description | Upgrade a Statamic addon from v5 to v6 — Vue 2→3 with the composition API, Vite + Tailwind v4, AddonServiceProvider boot rename, Inertia.js for Control Panel pages, the new @statamic/cms/ui component library, and replacing edalzell/forma with the native UserConfig.php pattern. Triggers on "upgrade Statamic addon", "Statamic v6 migration", "port to Statamic 6", "Vue 2 to Vue 3 in Statamic", "replace Forma config", "AddonServiceProvider migration", "Statamic addon v5 v6", or pasting a Statamic addon repo URL. |
You are upgrading a Statamic addon from v5 to v6. The biggest changes are in the Control Panel — Vue 2 → Vue 3, Inertia.js, Vite, Tailwind v4 — plus PHP 8.3 / Laravel 12 minimums and a long list of small API renames. This skill drives the upgrade in 8 phases. Do not skip phases; each one's verification step gates the next.
- Confirm you are in a Statamic addon repository (look for
composer.jsonwith"type": "statamic-addon"). - Confirm it currently targets Statamic v5 (
statamic/cms: ^5.*incomposer.json). - If either check fails, stop and tell the user what you found — do not start an upgrade speculatively.
- Frontend Livewire components. Statamic v6's breaking changes are CP-only. The only intersection is event renames (
GlobalSetSaved→GlobalVariablesSaved); flag and rename those if found, ignore the rest. - Payment gateway code, models, migrations, third-party SDK upgrades. Orthogonal to v6.
- Whether
marcorieser/statamic-livewire/edalzell/formathemselves have v6 releases. This skill removes Forma and replaces it with nativeUserConfig.php. If a Livewire bridge is needed for the CP it's a follow-up.
| # | Phase | Reference file |
|---|---|---|
| 1 | Audit & branch | references/00-workflow.md + references/01-audit-checklist.md |
| 2 | Dependencies (composer + npm) | references/02-composer-and-deps.md |
| 3 | Build tooling (Mix → Vite, TW v4) | references/04-vite-and-tailwind.md |
| 4 | Service provider rename + cleanups | references/03-service-provider.md |
| 5 | Config: Forma → UserConfig.php | references/08-userconfig-pattern.md |
| 6 | Vue 3 component migration | references/05-vue3-migration.md + references/06-fieldtype-migration.md |
| 7 | CP pages → Inertia | references/07-cp-pages-inertia.md |
| 8 | API/event renames + tests | references/09-api-breaking-changes.md + references/10-testing.md |
Phase order is deliberate: dependencies and tooling first so subsequent edits compile; service provider before config because config registration lives in it; Vue migration before Inertia pages because pages depend on Vue 3 components; API renames last because they're a sweep that benefits from everything else being settled.
- Read the phase's reference file before editing. Reference files have the concrete diffs, templates, and gotchas. The SKILL.md only orchestrates.
- One phase per logical commit. Each phase ends with a verification step (build succeeds, tests pass, page renders). Commit before moving on so rollback is cheap.
- Use the templates verbatim, then adapt. Files under
templates/are working v6 patterns lifted fromstatamic/seo-pro,duncanmcclean/statamic-cargo, andreachweb/statamic-ai-agent. Copy first, customise second. - Audit before editing. Phase 1 runs the grep recipes from
references/01-audit-checklist.mdto enumerate the v5 surface — Forma usages, Vue 2 files, Blade CP pages, event listeners. Each later phase uses this inventory as its worklist. - If the addon is Resrv specifically (
reachweb/statamic-resrv), also readreferences/resrv-playbook.mdafter Phase 1 — it has the concrete file map (5 fieldtypes, 19 CP components, 11 Blade CP views, Forma config location, etc.).
- Create a
v6-upgradebranch. - Run the grep checklist in
references/01-audit-checklist.md. Record findings in a short report (file count per category). - Run the addon's existing test suite and save the baseline (which tests pass today). You'll compare against this after Phase 8.
- If the addon is Resrv, read
references/resrv-playbook.mdand cross-check the audit against the known surface.
Verification: the audit report names every file you'll need to touch later. If something obvious is missing (e.g. no Vue files listed but resources/js/ clearly has them), fix your grep before moving on.
Open references/02-composer-and-deps.md and apply the diffs to composer.json and package.json.
Verification: composer install and npm install both resolve. You may see peer-dep warnings during npm install — note them but don't fix yet.
Open references/04-vite-and-tailwind.md. Replace vite.config.js, set up Tailwind v4, rename the JS entry from <addon>.js to cp.js, update protected $vite in the service provider.
Verification: npm run cp:build (or your build script) exits 0 and emits files under resources/dist/.
Open references/03-service-provider.md. Confirm extends AddonServiceProvider, rename boot() → bootAddon(), remove the deprecated API calls listed there, ensure protected $vite matches the new entry, and switch nav/permissions to the Nav::extend / Permission::group builder patterns.
Verification: php artisan config:clear && php artisan cache:clear then load the host site's CP — addon nav still appears, no exception in the Laravel log.
Open references/08-userconfig-pattern.md. Drop edalzell/forma, drop its boot hooks, copy the UserConfig.php and SettingsController.php templates into src/, write the blueprint to resources/blueprints/config.yaml, register the route in routes/cp.php, add a settings nav item with Nav::extend(...)->settings(...).
Verification: in the CP, open Settings → , edit a value, save, reload, value persists in resources/<addon-name>.yaml.
Open references/05-vue3-migration.md for general components and references/06-fieldtype-migration.md for fieldtype components specifically. Convert every .vue file from Options API to <script setup> (Composition API). Fieldtypes adopt the Fieldtype.use(emit, props) composable. Update Statamic.$components.register(...) calls to live inside Statamic.booting(() => {...}).
Do components in this order: mixins/composables → fieldtypes → list/panel/modal components. That way later components can import already-migrated helpers.
Verification: npm run cp:build still exits 0 with no Vue 2 plugin in the chain. Load a page with each fieldtype and confirm it mounts without console errors.
Open references/07-cp-pages-inertia.md. For each Blade view in resources/views/cp/*.blade.php:
- Create a matching Vue 3 page at
resources/js/pages/<Name>.vueusing<script setup>and components from@statamic/cms/ui. - Change the controller method to return
Inertia::render('<addon>::<Name>', [...]). - Register the page in
cp.jswithStatamic.$inertia.register('<addon>::<Name>', PageComponent). - Delete the old Blade view.
Verification: every CP route the addon registers loads without 500 or white-screen. Listings sort and filter. Forms submit and validate.
Open references/09-api-breaking-changes.md. It is a single grep-driven cheatsheet — run each grep, apply the rename, move on. Then open references/10-testing.md to switch the test base class to Statamic\Testing\AddonTestCase and bump phpunit/testbench constraints.
Verification: vendor/bin/phpunit (or pest) runs to completion. Every test that passed in the Phase 1 baseline still passes. Diff the failures — anything new is a regression introduced by the upgrade, not a v5-era preexisting failure.
After Phase 8:
- Summarise what changed (composer/npm deps, files touched per phase, anything you couldn't auto-migrate).
- List anything still pending human judgement (e.g. a complex Vue 2 component with unusual patterns you flagged for manual review).
- Suggest a manual smoke test path in the host site CP.
Do not open a PR, push, or merge unprompted. The user drives those steps.