npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bryanbuchs/generator-component

v6.0.0

Published

CLI tool for Drupal SDC + Storybook components

Readme

generator-component

Generates Drupal Single Directory Component (SDC) boilerplate with integrated Storybook stories. A lightweight, interactive CLI tool that replaces the Yeoman-based generator.

Features

  • 🎯 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

Requirements

  • Node.js 14+
  • A Drupal project with SDC support (Drupal 10.1+) or a theme using SDC conventions

Installation

Global (Recommended)

Install globally to use generator-component from any project:

npm install -g @bryanbuchs/generator-component

Local (Project-specific)

npm install --save-dev @bryanbuchs/generator-component
npx generator-component

Usage

From your theme directory, run:

generator-component

This launches an interactive prompt that guides you through component creation. Components are generated in components/{component-tag}/.

Interactive Prompts

1. Component Name

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

2. Component Group

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

3. Component Description

A brief description used in generated files as documentation.

4. Field Definitions

Define component fields/properties:

Field Types

  • String - Text value. Example: title, label, heading
  • Boolean - True/false flag. Auto-detected for names starting with is or has
  • 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

Field Requirements

Mark fields as required to:

  • Enforce validation in component.yml
  • Generate Storybook controls
  • Document in component metadata

Field Examples

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.

5. Behavior.js File

Include JavaScript for component interactions/initialization. Generates:

  • {tag}.behavior.js - JavaScript source
  • Entry in {tag}.library.js for Drupal

6. Style Format

Choose stylesheet format or skip:

  • LESS - LESS preprocessor (compiles to CSS)
  • CSS - Plain CSS
  • -none- - No stylesheet (framework-provided styles)

Generated Files

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)

File Details

component.yml

Drupal SDC metadata defining:

  • Component display name and description
  • Field schema and validation
  • Props configuration for Twig rendering
  • Required vs optional fields

.twig

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

.stories.js

Storybook configuration:

  • Component display in Storybook hierarchy
  • Example story with default args
  • Field documentation in controls
  • Ready for visual testing and documentation

.library.js

Drupal library declaration:

  • Registers CSS and JS for inclusion
  • Proper asset paths for dist/ build output
  • Required when styles or behavior.js are included

.less / .css

Style file (optional):

  • Placeholder for component-specific styles
  • Uses BEM naming convention based on component tag
  • Ready for preprocessing (LESS) or direct usage (CSS)

.behavior.js

JavaScript file (optional):

  • Drupal-style behavior attachment
  • Receives component selector from {tag} CSS class
  • Use for event listeners, initialization, etc.

Component Naming

The generator automatically transforms component names through several steps:

Example: featured-product-card in entity group

  1. Input: featured-product-card
  2. Normalize: featured product card
  3. 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)
  4. CSS classes: entity, entity-featured-product-card

Rules

  • 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 Type Examples

String Field

Field: title (string, required)

Generated Twig:
  {{ title }}

Generated Storybook:
  args: { title: 'TITLE' }

Array Field

Field: items (array, optional)

Generated Twig:
  {% for item in items %}
    {{ item }}
  {% endfor %}

Generated Storybook:
  args: { items: ['ITEM', 'ITEM', 'ITEM'] }

Slot

Field: content (slot)

Generated Twig:
  {% block content %}
    Content slot
  {% endblock %}

Generated Stories:
  No direct arg (passed as HTML block in Storybook)

Customization After Generation

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

Integration with Drupal

Setting Up Components

  1. Ensure your theme has components directory at root
  2. Run generator-component to create component
  3. Add to your theme's package.json build process:
    • Compile LESS/CSS if needed
    • Build JS for distribution

Using Components in Twig

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
} %}

Component Namespace Syntax

The modern Drupal SDC component syntax uses theme namespaces:

Pattern: THEMENAME:component-tag

Examples:

  • custom_theme:entity-featured-product-card
  • my_theme:block-card
  • my_theme:form-button

Replace THEMENAME with your actual theme name (found in your theme's .info.yml file).

Understanding the Component Tag

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: entityentity-card
  • Component: featured-product, Group: blockblock-featured-product
  • Component: button, No group → button

With Block Context

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']
} %}

Integration with Storybook

  1. Configure Storybook to include the components/ directory
  2. Run Storybook
  3. Generated stories appear in sidebar under component group
  4. Use stories for:
    • Component development and testing
    • Visual documentation
    • Interaction testing

Project Structure

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

Architecture

The generator operates in two phases:

  1. Prompting (lib/index.js:prompting())

    • Interactive CLI prompts
    • Collects user input
    • Returns answers object
  2. Writing (lib/index.js:writing())

    • Transforms answers to component metadata
    • Renders EJS templates
    • Writes files to disk

Dependencies

  • enquirer - Interactive CLI prompts
  • inflection - String transformations (pluralize, camelize, etc.)
  • ejs - Template rendering engine
  • Node.js fs/path - File system and path utilities

Development

Local Setup

git clone <repo>
cd generator-component
npm install
npm link  # Makes `generator-component` available globally

Testing

mkdir test-project
cd test-project
npm init -y
generator-component  # Test the interactive flow

Troubleshooting

Command not found

If 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-component

Files not creating in correct directory

Ensure you run generator-component from a directory where you want the components/ folder created. It will be created at:

./components/{component-tag}/

Template errors

If templates render with undefined values, check:

  1. Field names are defined correctly
  2. Field types are supported (string, array, boolean, object, number, slot)
  3. Component name contains no special characters (they're normalized)

License

See LICENSE file in repository.

Contributing

Contributions welcome! Please submit issues and pull requests to the GitHub repository.