michtio/craftcms-claude-skills/craft-twig-guidelines
Claude Code and agent skill by michtio/craftcms-claude-skills
- community
Checking that the SKILL.md file is still in the repository.
Twig coding standards and conventions for Craft CMS 5 templates. ALWAYS load this skill when writing, editing, or reviewing any .twig file in a Craft CMS project — even for small edits. Covers: variable naming (camelCase, no abbreviations), null handling (?? operator, ??? with empty-coalesce plugin), whitespace control ({%- trimming, NOT {%- minify -%}), include isolation (always use 'only'), Craft Twig helpers ({% tag %}, tag(), attr(), |attr filter, |parseAttr, |append, svg()), collect() for props and class collections, .implode(), comment headers with ========= separators on component files, and common pitfalls (snake_case, macros as components, hardcoded colors).
Install
npx vskill@latest install michtio/craftcms-claude-skills/craft-twig-guidelinesSKILL.md
Twig Coding Standards — Craft CMS 5
Coding conventions for Twig templates in Craft CMS 5 projects. These apply to all Twig code — atomic components, views, layouts, builders, partials.
Companion Skills — Always Load Together
When this skill triggers, also load:
- `craft-site` — Template architecture and component patterns. Required when creating or editing components, layouts, views, or builders.
- `craft-content-modeling` — Content architecture. Required when template code involves element queries, field access, or section decisions.
For Twig architecture patterns (atomic design, routing, builders), see the craft-site skill. For PHP coding standards, see craft-php-guidelines.
Documentation
- Twig in Craft: https://craftcms.com/docs/5.x/development/twig.html
- Template tags: https://craftcms.com/docs/5.x/reference/twig/tags.html
- Template functions: https://craftcms.com/docs/5.x/reference/twig/functions.html
- Twig 3 docs: https://twig.symfony.com/doc/3.x/
Use WebFetch on specific doc pages when something isn't covered here.
Variable Naming
Single-word, descriptive, lowercase preferred. When multi-word is needed, use camelCase.
No abbreviations: element not el, button not btn, navigation not nav, description not desc.
Prefer single-word names when context makes the meaning clear (e.g. heading inside a component is better than sectionHeading). But multi-word camelCase is perfectly fine when needed for clarity.
Null Handling
?? is the default. Always safe, always portable.
??? (empty coalesce) is acceptable if the project already has nystudio107/craft-emptycoalesce or nystudio107/craft-seomatic installed — both provide the operator. But never install a plugin just for ???. Check composer.json first.
Craft 5 supports the nullsafe operator (?.). Use it for deep traversal through chains that may have null links — it propagates null cleanly without the verbose is defined and is not null dance:
?? stays the right tool for simple "value or fallback" cases; ?. is for chains where intermediate links may be missing. Don't reach for ?. on a single property access — it adds noise without adding safety.
Whitespace Control
Use {%- and {{- for whitespace trimming. Never use {%- minify -%}.
Apply whitespace control on tags that produce unwanted blank lines in output. Not every tag needs it — use where visible output whitespace matters.
Include Isolation
Every {% include %} MUST use only. No exceptions.
Without only, a component can silently depend on variables from its parent scope, creating invisible coupling.
No Macros for Components
Never use {% macro %} for UI components. Macros don't support extends/block and their scoping model differs from includes.
Macros are acceptable for utility functions that return strings (e.g., formatting helpers), not for rendering UI.
Comment Headers
Every component file gets a section header comment:
Props files, variant files, views, layouts — all get headers. The ========= separator matches the PHP convention from craft-php-guidelines.
Craft Twig Helpers
{% tag %} — Polymorphic Elements
Primary tool for rendering elements whose tag name depends on props.
Rules:
- Variable name must be descriptive:
element,heading,wrapper. Neverel,hd. falseomits an attribute entirely from the rendered HTML.nullalso omits. Usefalsewhen explicitly excluding,nullwhen absent.classaccepts arrays with automatic falsy filtering.ariaanddataaccept nested hashes that expand toaria-*/data-*attributes.
tag() — Inline Element Function
For simple elements without complex inner content:
text:key = HTML-encoded content.html:key = raw HTML content (trusted input only).- Self-closing elements (
img,input,br) handled automatically.
attr() — Attribute Strings
For building attributes in non-tag contexts:
Returns a space-prefixed attribute string. Same false-means-omit and class array filtering as {% tag %}.
|attr Filter
For merging attributes onto existing HTML strings:
|parseAttr Filter
For extracting attributes from an HTML string into a hash for manipulation:
|append Filter
For adding content to an element string:
svg() Function
Combine with |attr for classes and aria attributes. Use |append for accessible labels inside the SVG.
url() with false Params (Craft 5.11+)
Passing false as the second argument strips every query-string param from an absolute URL. Canonical links, share URLs, and "clear filters" links:
An array still merges params in; false removes them all. The stripping only applies when the passed-in URL is absolute, so feed it a full URL, not a path. PHP has the same call as UrlHelper::url($url, false), plus UrlHelper::removeParams($url, [...]) and UrlHelper::removeAllParams($url) for finer control. Before 5.11, rebuild the clean URL with siteUrl(craft.app.request.pathInfo) instead.
heading() / h() / h1()…h6() — Programmatic Headings (Craft 5.10+)
Build heading tags from a dynamic level without string-concatenation. Useful in components that receive a level prop and need to render the matching tag without doing tag('h' ~ level, text) manually.
These are stateless tag builders — there's no auto-incrementing or current-level tracking. Components that need to thread a level across nested contexts still pass it as a prop. heading() throws InvalidArgumentException when level is outside 1-6.
Filter Additions (Craft 5.10+)
Filtering and Mapping — Default to collect()
For data manipulation in templates, default to `collect()` — one consistent, chainable API (where, firstWhere, groupBy, keyBy, unique, pluck, map, filter, sortByDesc) instead of mixing idioms:
The bare Twig/Craft array filters are fine for a single trivial operation inline — {% for e in entries|filter(e => e.enabled) %} — where a Collection adds nothing. But Twig's |filter/|map return plain arrays and Craft's |where/|firstWhere/|group/|index go through ArrayHelper, so they don't chain like Collection methods; once you need more than one step, switch to collect(). Don't mix both styles arbitrarily.
There is no `|indexBy` filter — key a list with |index (or .keyBy() on a Collection) and bucket with |group (or .groupBy()). (|where, |firstWhere, |contains, |group, |index, |explodeClass/|explodeStyle are all Craft-registered filters.)
Safe Output and Inline Assets
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/craft-twig-guidelines/SKILL.md
Popularity
- Repository stars
- 71
- Repository forks
- 6
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/michtio/craftcms-claude-skills/craft-twig-guidelines)