component-scaffolding
Component Scaffolding
Generate component skeletons for a Drupal theme using Twig, web components, and Miyagi for validation.
Trigger Phrases
- "Add component skeleton at patterns/..."
- "Create new component..."
- "Scaffold component..."
- Creating/updating schema.yaml or mocks.yaml files
Configuration
Component Library Root
This skill assumes it lives within a component library project, e.g.:
apps/component-library/
├── .claude/
│ └── skills/
│ └── component-scaffolding/ ← this skill
├── src/
│ ├── components/
│ └── css/
└── <theme-name>.libraries.yml
The component library root is three levels up from this skill (i.e., ../../.. relative to this SKILL.md).
Theme Name Discovery
The <theme-name> placeholder must be replaced with the actual Drupal theme name. To determine it:
- Navigate to the component library root
- Find the
*.libraries.ymlfile — the filename prefix is the theme name - Example:
circle_dot.libraries.yml→ theme name iscircle_dot
If the theme name cannot be determined from existing files, ask the user.
File Templates
1. Twig Template: <component-name>.twig
{{ attach_library("<theme-name>/pattern-<component-name>") }}
<div class="<ComponentName>">
{# Component implementation #}
</div>
- Library name:
pattern-<component-name>(kebab-case) - CSS class:
<ComponentName>(PascalCase) - Single tab indentation
2. CSS: <component-name>.css
/** @define <ComponentName>; */
.<ComponentName > {
/* Component styles */
}
- PascalCase in
@definecomment - Tab indentation
3. JavaScript: <component-name>.js
Only create if explicitly needed. Skip if user says "no JavaScript", "CSS only", etc.
// @ts-check
class <ComponentName> extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.#addEventListeners();
}
/**
* Add event listeners
*/
#addEventListeners() {
// Add event listeners here
}
}
customElements.define("<component-name>", <ComponentName>);
- PascalCase class name
- NO prefix on custom element name (use kebab-case directly)
- Only
#addEventListeners()method in skeleton - NO
#elementsfield or#getElements()method
4. Schema: schema.yaml
$schema: http://json-schema.org/draft-07/schema#
$id: /<tier>/<component-name>
type: object
required:
- property1
additionalProperties: false
properties:
$idmatches component tier path- Include
requiredarray with placeholder names - Leave
properties:empty in skeleton - 2-space indentation (YAML standard)
For detailed schema patterns, see references/schema-and-mocks.md.
5. Mocks: mocks.yaml
- Single blank line only in skeleton
- User adds their own mock data later
For mock data patterns, see references/schema-and-mocks.md.
6. CSS Entry Point: src/css/<component-name>.css
@import url("../components/<tier>/<component-name>/<component-name>.css")
layer(components);
Note: If the component is an element, you can use the
elements.cssentry point instead.
7. Library Definition: <theme-name>.libraries.yml
Add entry alphabetically within the appropriate tier section:
pattern-<component-name>:
header: true
css:
component:
build/assets/css/<component-name>.css: {}
js:
build/assets/components/<tier>/<component-name>/<component-name>.js:
attributes:
type: module
- Omit the
js:block entirely if no JavaScript file is created - Maintain blank line between library definitions
- Omit the
css:block entirely if the component is an element
Naming Conventions
| Item | Format | Example |
|---|---|---|
| Directory/files | kebab-case | share-button |
| CSS class | PascalCase | ShareButton |
| JS class | PascalCase | class ShareButton |
| Custom element | kebab-case, NO prefix | share-button |
| Library name | <prefix>-<kebab> |
pattern-share-button |
| Schema $id | /<tier>/<kebab> |
/patterns/share-button |
Component Tiers
| Tier | Location | Library Prefix |
|---|---|---|
| Elements | src/components/elements/ |
element- |
| Patterns | src/components/patterns/ |
pattern- |
| Template Components | src/components/template-components/ |
template-component- |
| Templates | src/components/templates/ |
template- |
Workflow
- Create component directory:
src/components/<tier>/<component-name>/ - Create component files (twig, css, schema.yaml, mocks.yaml, and js only if needed)
- Create CSS entry point:
src/css/<component-name>.css - Add library definition to
<theme-name>.libraries.yml(alphabetically in tier section) - Run linters to verify
Optional Files
Pay attention to user requests indicating which files to skip:
| User says | Action |
|---|---|
| "no JavaScript" / "CSS only" | Skip .js file, omit js: from library |
| "no CSS" / "JavaScript only" | Skip .css files, omit css: from library |
| "schema only" / "just the schema" | Create only schema.yaml |
Notes
- Skeletons provide structure, not functionality
- All files use tabs except YAML (2 spaces)
- Run linters after creation to verify
More from schalkneethling/webdev-agent-skills
frontend-security
Audit frontend codebases for security vulnerabilities and bad practices. Use when performing security reviews, auditing code for XSS/CSRF/DOM vulnerabilities, checking Content Security Policy configurations, validating input handling, reviewing file upload security, or examining Node.js/NPM dependencies. Target frameworks include web platform (vanilla HTML/CSS/JS), React, Astro, Twig templates, Node.js, and Bun. Based on OWASP security guidelines.
188semantic-html
Write well-considered semantic HTML that serves all users. Use when creating components, page structures, or reviewing markup. Emphasizes native HTML elements over ARIA. Treats proper document structure and accessibility as foundations rather than afterthoughts.
163css-coder
CSS authoring guidance emphasizing web standards, accessibility, and performance. Use when writing, reviewing, or refactoring CSS. Provides patterns, snippets, and conventions that prioritize native CSS over frameworks, semantic structure, and maintainable code. Refer to references/patterns.md for specific patterns and snippets.
41css-tokens
Provides foundational CSS design tokens (custom properties) for typography, spacing, colors, borders, z-index, and transitions. Use when setting up a base token system for a web project.
17frontend-testing
Write tests that start with acceptance criteria, then add implementation tests for robustness. Use when writing unit tests (Vitest), end-to-end tests (Playwright), visual regression tests, or accessibility tests. Emphasizes user-centric testing, semantic locators, accessibility validation, and the balance between acceptance and implementation testing.
16component-usage-analysis
Analyse component dependencies and usage patterns in a Drupal/Twig component library. Use when user asks to find where a component is used, check if a component can be safely removed, audit component dependencies, find components using specific properties, or analyse impact of refactoring a component.
13