Generates Drupal Single Directory Component (SDC) boilerplate with integrated Storybook stories. A lightweight, interactive CLI tool that replaces the Yeoman-based generator.
- 🎯 Interactive Prompts - Guided component generation without CLI arguments
- 📦 Complete Scaffolding - Creates all necessary SDC and Storybook files
- 🎨 Flexible Styling - Choose between LESS, CSS, or no stylesheet
- 🧩 Smart Field Types - String, boolean, number, object, array, and slot support
- ⚡ Zero Yeoman Overhead - Lightweight, fast, and simple
- 📚 Storybook Ready - Generated stories include field documentation and examples
- Node.js 14+
- A Drupal project with SDC support (Drupal 10.1+) or a theme using SDC conventions
Install globally to use generator-component from any project:
npm install -g @bryanbuchs/generator-componentnpm install --save-dev @bryanbuchs/generator-component
npx generator-componentFrom your theme directory, run:
generator-componentThis launches an interactive prompt that guides you through component creation. Components are generated in components/{component-tag}/.
The base name of your component (e.g., card, button, hero-banner)
- Spaces and punctuation are normalized to kebab-case
- Used to generate the component tag and CSS classes
Organize components in Storybook stories (optional). Choose from:
- Block - Block-level components
- Content - Content-related components
- Entity - Entity-based components
- Field - Field formatters
- Form - Form-related components
- Global - Global/layout components
- Media - Media components
- Nav - Navigation components
- Node - Node-type components
- Page - Page-level components
- Paragraph - Paragraph-type components
- Region - Region components
- View - View-based components
- Widget - Widget components
- -none- - Skip grouping
The group combines with the component name to create the final tag:
component-name: card+group: entity→ tag:entity-card
A brief description used in generated files as documentation.
Define component fields/properties:
- String - Text value. Example:
title,label,heading - Boolean - True/false flag. Auto-detected for names starting with
isorhas - Number - Numeric value. Example:
count,width,priority - Array - Collection of items. Use plural names like
items,cards,people - Object - Structured data. Example:
metadata,config,settings - Slot - Twig block for nested content. Example:
content,body,footer
Mark fields as required to:
- Enforce validation in component.yml
- Generate Storybook controls
- Document in component metadata
Field: title (string, required)
Field: subtitle (string, optional)
Field: isActive (boolean - auto-detected)
Field: items (array)
Field: content (slot - not required)
Leave field name blank to finish adding fields.
Include JavaScript for component interactions/initialization. Generates:
{tag}.behavior.js- JavaScript source- Entry in
{tag}.library.jsfor Drupal
Choose stylesheet format or skip:
- LESS - LESS preprocessor (compiles to CSS)
- CSS - Plain CSS
- -none- - No stylesheet (framework-provided styles)
Each component generates a directory with:
components/{component-tag}/
├── {tag}.component.yml # Drupal SDC metadata (required)
├── {tag}.twig # Component template
├── {tag}.stories.js # Storybook configuration
├── {tag}.library.js # Drupal library registry (if CSS/JS)
├── {tag}.less or .css # Stylesheet (optional)
└── {tag}.behavior.js # JavaScript behavior (optional)
Drupal SDC metadata defining:
- Component display name and description
- Field schema and validation
- Props configuration for Twig rendering
- Required vs optional fields
Twig template for rendering the component:
- Receives variables from parent templates
- Includes CSS classes
- Renders fields with appropriate syntax (loops for arrays, conditionals for slots)
- Ready for Drupal integration
Storybook configuration:
- Component display in Storybook hierarchy
- Example story with default args
- Field documentation in controls
- Ready for visual testing and documentation
Drupal library declaration:
- Registers CSS and JS for inclusion
- Proper asset paths for dist/ build output
- Required when styles or behavior.js are included
Style file (optional):
- Placeholder for component-specific styles
- Uses BEM naming convention based on component tag
- Ready for preprocessing (LESS) or direct usage (CSS)
JavaScript file (optional):
- Drupal-style behavior attachment
- Receives component selector from {tag} CSS class
- Use for event listeners, initialization, etc.
The generator automatically transforms component names through several steps:
- Input:
featured-product-card - Normalize:
featured product card - Generate names:
- tag:
entity-featured-product-card(kebab-case, for CSS/filenames) - name:
EntityFeaturedProductCard(PascalCase, for JavaScript/Storybook) - label:
Featured Product Card(Title Case, for display)
- tag:
- CSS classes:
entity,entity-featured-product-card
- Spaces, dashes, and underscores normalize to spaces
- Consecutive spaces collapse to single space
- Group + component creates the final tag (if group selected)
- All names are lowercase in CSS/filenames
Field: title (string, required)
Generated Twig:
{{ title }}
Generated Storybook:
args: { title: 'TITLE' }
Field: items (array, optional)
Generated Twig:
{% for item in items %}
{{ item }}
{% endfor %}
Generated Storybook:
args: { items: ['ITEM', 'ITEM', 'ITEM'] }
Field: content (slot)
Generated Twig:
{% block content %}
Content slot
{% endblock %}
Generated Stories:
No direct arg (passed as HTML block in Storybook)
All generated files use standard Drupal/Twig/Storybook conventions and are fully editable:
- component.yml - Adjust schema, add schema validation
- .twig - Refine markup, add filters, update structure
- .stories.js - Add story variations, update documentation
- .library.js - Add build assets, CSS preprocessing
- .less/.css - Add component-specific styles
- .behavior.js - Add component interactivity
- Ensure your theme has
componentsdirectory at root - Run
generator-componentto create component - Add to your theme's
package.jsonbuild process:- Compile LESS/CSS if needed
- Build JS for distribution
Component is immediately available in Twig templates using the new Drupal SDC namespace syntax:
{% include 'THEMENAME:entity-featured-product-card' with {
title: 'Featured Product',
items: featured_products
} %}The modern Drupal SDC component syntax uses theme namespaces:
Pattern: THEMENAME:component-tag
Examples:
custom_theme:entity-featured-product-cardmy_theme:block-cardmy_theme:form-button
Replace THEMENAME with your actual theme name (found in your theme's .info.yml file).
The component-tag comes from the generator and follows this pattern:
- If you selected a group + component:
group-name-component-name - If no group selected:
component-name
Examples:
- Component:
card, Group:entity→entity-card - Component:
featured-product, Group:block→block-featured-product - Component:
button, No group →button
Components can also be referenced in block templates:
{# In a block template #}
{% include 'THEMENAME:entity-featured-product-card' with {
title: block.content['#title'],
items: block.content['#items']
} %}- Configure Storybook to include the
components/directory - Run Storybook
- Generated stories appear in sidebar under component group
- Use stories for:
- Component development and testing
- Visual documentation
- Interaction testing
generator-component/
├── bin/
│ └── cli.js # Executable entry point
├── lib/
│ └── index.js # Core generator logic
├── templates/ # EJS template files
├── package.json # Dependencies and bin configuration
└── README.md # This file
The generator operates in two phases:
-
Prompting (
lib/index.js:prompting())- Interactive CLI prompts
- Collects user input
- Returns answers object
-
Writing (
lib/index.js:writing())- Transforms answers to component metadata
- Renders EJS templates
- Writes files to disk
- enquirer - Interactive CLI prompts
- inflection - String transformations (pluralize, camelize, etc.)
- ejs - Template rendering engine
- Node.js fs/path - File system and path utilities
git clone <repo>
cd generator-component
npm install
npm link # Makes `generator-component` available globallymkdir test-project
cd test-project
npm init -y
generator-component # Test the interactive flowIf generator-component is not found after installation:
# Try npm link (for development)
npm link @bryanbuchs/generator-component
# Or reinstall globally
npm install -g @bryanbuchs/generator-componentEnsure you run generator-component from a directory where you want the components/ folder created. It will be created at:
./components/{component-tag}/
If templates render with undefined values, check:
- Field names are defined correctly
- Field types are supported (string, array, boolean, object, number, slot)
- Component name contains no special characters (they're normalized)
See LICENSE file in repository.
Contributions welcome! Please submit issues and pull requests to the GitHub repository.