Step-by-step guide for scaffolding a new React component from scratch. Covers copying an existing component as a base, creating the required index.jsx and component.yml files, naming conventions (snake_case machineName, no project prefixes), creating the matching Storybook story file, reusing existing components via imports, composability patterns, and internal component setup (status false). Use when a needed component does not yet exist in src/components/ and must be created.
From drupal-canvasnpx claudepluginhub ajv009/drupal-devkit --plugin drupal-canvasThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides agent creation for Claude Code plugins with file templates, frontmatter specs (name, description, model), triggering examples, system prompts, and best practices.
Creating a component is an act of design. Before scaffolding files, understand what the component needs to represent — its content areas, layout structure, and the CMS data it will render. The template you start from is a starting point, not a constraint.
Before creating any component:
{text} prop — even if it's called "footer."After creation, verify: can this component represent the full structure of its target section? Every content area in the source should map to a prop or slot. If it can't, the component is incomplete.
When asked to create a new component:
src/components/ to find a similar component that can serve as a
starting point (e.g., use blockquote as a base for an "alert" component, or
button for any interactive element)src/components/<new_name>/src/stories/CRITICAL: Every component MUST have its own individual story file. When
copying from existing components, always copy both the component folder AND its
corresponding story file. The story file naming convention is
<component-name>.stories.jsx (using kebab-case with hyphens).
This approach ensures consistent patterns for component.yml structure, JSX
conventions, and Storybook story format across all components.
Example: To create a new "Alert" component based on the Blockquote example:
cp -r src/components/blockquote src/components/alert
cp src/stories/components/blockquote.stories.tsx src/stories/components/alert.stories.tsx
Then modify the copied files to implement the Alert component.
Components use the @/components import alias, which points to
src/components. When you copy and modify existing components, the imports
will work automatically.
When copying a component as a template, you must also copy its dependencies:
index.jsx@/components/<name> importssrc/components/@/components/<name> importsExample: Copying hero which imports heading and button:
src/components/heading/ — exists? Skip. Missing? Copy.src/components/button/ — exists? Skip. Missing? Copy.heading's imports — imports @/components/text? Copy if missing.Never overwrite existing components during dependency copying. Only copy what's missing.
Use simple, generic names. Never prefix component names with the project or site name. Components should be reusable and their names should describe their purpose, not their origin.
# Correct - simple, descriptive names
footer
hero
navigation
contact_form
# Wrong - prefixed with project/site name
acme_footer
mysite_hero
projectx_navigation
This ensures components remain portable and their names clearly communicate their function rather than their project context.
Always check src/components/ before creating new UI elements. When
building a component that needs common UI elements (buttons, headings, images,
etc.), import and use existing components rather than duplicating their
functionality.
// GOOD: Import and use the existing button component
import Button from '@/components/button';
const NewsletterSignup = ({ onSubmit }) => (
<form onSubmit={onSubmit}>
<input type="email" placeholder="Enter your email" />
<Button variant="primary">Subscribe</Button>
</form>
);
// BAD: Duplicating button styles instead of reusing the component
const NewsletterSignup = ({ onSubmit }) => (
<form onSubmit={onSubmit}>
<input type="email" placeholder="Enter your email" />
<button className="rounded bg-primary-600 px-4 py-2 text-white">
Subscribe
</button>
</form>
);
This ensures visual consistency, reduces duplication, and makes updates easier since changes to a shared component automatically apply everywhere it's used.
Design components for composability. By default, avoid building layout
constraints (like max-width or centering) into individual components. Layout
components such as section handle width constraints when composing pages, so
most components should remain flexible and adapt to their container.
Include built-in layout constraints when the component doesn't make sense in any
other layout context (such as header or footer), or when the design
specifically requires it.
// GOOD: Component adapts to its container width
const Card = ({ title, children }) => (
<div className="rounded-lg border p-4">
<h3>{title}</h3>
{children}
</div>
);
// BAD: Component has built-in width constraints (limits composability)
const Card = ({ title, children }) => (
<div className="mx-auto max-w-md rounded-lg border p-4">
<h3>{title}</h3>
{children}
</div>
);
Every component must satisfy the 4-part contract:
index.jsx — React component implementation (default export)component.yml — Canvas metadata defining props, slots, and enumsmachineName — lowercase snake_case (preferred) or kebab-casesrc/stories/components/If any part is missing, the component is incomplete and will fail upload or editor rendering.
npm run code:fix (Prettier + ESLint + Canvas requirements), then npm run canvas:validate, then npm run canvas:ssr-testnpm run canvas:upload -- -- -c <name> only after validation passesCRITICAL: Every component folder in src/components/ MUST contain two
files:
src/components/<component_name>/
├── index.jsx # React component source code (REQUIRED)
└── component.yml # Component metadata and props (REQUIRED)
Never create a component folder without both files. The index.jsx contains
the actual React component implementation. The component.yml defines the
component's metadata, props, and slots for Drupal Canvas.
The directory name must match machineName. The component folder name must
exactly match the machineName value defined in component.yml. Use
snake_case as the preferred format, though kebab-case is also supported.
After creating components, verify the folder structure:
# List all component folders and their contents
ls -la src/components/*/
# Verify each new component has both required files
ls src/components/<component_name>/index.jsx
ls src/components/<component_name>/component.yml
If a component folder is missing either file, the component is incomplete and
will not work. Both index.jsx and component.yml are required.
For internal re-use that should not be exposed to content editors via the
library of components, ensure you set status: false in the component.yml
file.
Utility/helper function can be placed in a utils_<name> component with an
React component as a default export. These should always be internal components,
so status: false MUST be set in the component.yml file.
Every non-internal component should have a corresponding story file in
src/stories/components/. Where appropriate, internal components should also
have a story file.
Use the stories skill when creating or modifying stories.
When creating components for Drupal CMS, consult the official platform documentation to ensure your component follows platform conventions and avoids known pitfalls. Use the canvas-docs-explorer skill:
/canvas-docs-explorer creating custom components
Important: never remove components via the Component Library UI (known bug that can break the site). Use the Code component panel instead.
For the canonical component contract and naming conventions, see the canvas-starter reference skills for component definitions.