$npx -y skills add michtio/craftcms-claude-skills --skill craftcmsCraft CMS 5 plugin and module development — extending Craft with PHP. Covers elements, element queries, services, models, records, controllers, migrations, queue jobs, console commands, field types, native fields, events, behaviors, Twig extensions, widgets, filesystems, permissi
| 1 | # Craft CMS 5 — Extending (Plugins & Modules) |
| 2 | |
| 3 | Reference for extending Craft CMS 5 through plugins and modules. Covers everything from elements and services to controllers, migrations, fields, and events. |
| 4 | |
| 5 | This skill is scoped to **extending** Craft — building plugins, modules, custom element types, field types, and backend integrations. For site/platform development (content modeling, sections, entry types, Twig templating, plugin selection), see the `craft-site` skill. |
| 6 | |
| 7 | ## Companion Skills — Always Load Together |
| 8 | |
| 9 | When this skill triggers, also load: |
| 10 | |
| 11 | - **`craft-php-guidelines`** — PHPDoc standards, section headers, naming conventions, class organization, ECS/PHPStan, verification checklist. Required for any PHP code. |
| 12 | - **`ddev`** — All commands run through DDEV. Required for running ECS, PHPStan, scaffolding, and tests. |
| 13 | - **`craft-garnish`** — When working on CP JavaScript, asset bundles, or interactive CP components. Covers Garnish's class system, UI widgets (Modal, HUD, DisclosureMenu, Select), drag system, and the Craft.* JS class pattern. |
| 14 | - **`craft-cloud`** — When the project is hosted on Craft Cloud (detect via `craft-cloud.yaml` at the repo root or `craftcms/cloud` in `composer.json`). Required for plugin Cloud-compatibility constraints — `App::isEphemeral()` guards, asset-bundle CDN publishing, 15-minute queue-job cap, `csrfInput()` function over raw token output, and the `cloud/up` deploy lifecycle events. |
| 15 | |
| 16 | ## Documentation |
| 17 | |
| 18 | - Extend guide: https://craftcms.com/docs/5.x/extend/ |
| 19 | - Class reference: https://docs.craftcms.com/api/v5/ |
| 20 | - Generator: https://craftcms.com/docs/5.x/extend/generator.html |
| 21 | |
| 22 | Use `WebFetch` on specific doc pages when a reference file doesn't cover enough detail. |
| 23 | |
| 24 | ## Common Pitfalls (Cross-Cutting) |
| 25 | |
| 26 | - Always use `addSelect()` in `beforePrepare()` — it's the Craft convention and safely additive when multiple extensions contribute columns. |
| 27 | - Queue workers run in primary site context — use `->site('*')` for cross-site queries. |
| 28 | - Including `id` in `getConfig()` — project config uses UIDs, never database IDs. |
| 29 | - Business logic in models or controllers — services are where logic belongs. |
| 30 | - Modules need manual template root, translation, and controllerNamespace registration — nothing is automatic. |
| 31 | - `DateTimeHelper` in elements/queries, `Carbon` in services — never mix in the same class. |
| 32 | - Hardcoding `/admin` in CP URLs — `cpTrigger` is configurable. Use `UrlHelper::cpUrl()` in PHP, `cpUrl()` in Twig. |
| 33 | - Passing `$request->getBodyParams()` directly to `savePluginSettings()` on split-settings pages — only submitted keys persist, other settings are silently dropped. Load the full settings model first, update properties, then save. |
| 34 | |
| 35 | ## Reference Files |
| 36 | |
| 37 | Read the relevant reference file(s) for your task. Multiple files often apply together. |
| 38 | |
| 39 | **Task examples:** |
| 40 | - "Build a custom element type" → read `elements.md` (Architecture section first) + `element-index.md` + `fields.md` + `migrations.md` + `cp.md` |
| 41 | - "Build a hierarchical/tree element type" → read `elements.md` (Architecture: One Element Class with Native Structure) |
| 42 | - "Add a webhook endpoint" → read `controllers.md` + `events.md` |
| 43 | - "Create a queue job that syncs elements" → read `queue-jobs.md` + `elements.md` + `debugging.md` |
| 44 | - "Add a settings page with form fields" → read `controllers.md` + `cp.md` + `architecture.md` |
| 45 | - "Register a custom field type" → read `fields.md` + `events.md` |
| 46 | - "Fix PHPStan errors" → read `quality.md` |
| 47 | - "Add a dashboard widget" → read `cp-components.md` (Dashboard Widgets) + `events.md` (Widget Types section) |
| 48 | - "Expose template variables for plugin users" → read `events.md` (Twig Extensions section) |
| 49 | - "Attach custom methods to entrie |