# Nebula Component Creation

> Create React components by copying and modifying examples from `examples/components/`. Use when asked to (1) Create, add, or build a new component, (2) Copy an example component to `src/components/`, (3) Add a component with dependencies. Handles dependency resolution and ensures each component has `index.jsx` and `component.yml`.

- Skill: `acquia/nebula-component-creation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add acquia/nebula-component-creation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/acquia/nebula-component-creation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: acquia (https://skillmd.com/u/acquia)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/acquia/nebula-component-creation

---


Preview coverage requirements are delegated to `canvas-workbench` (see
`canvas-workbench/references/components.md` for Workbench component review flow,
and `canvas-component-definition/references/component-mocks.md` for `mocks.json`
rules).

## Workflow

### Creating a new component

Always start from an example. When asked to create a new component:

1. **Find a similar example** in `examples/components/` that can serve as a
   starting point (e.g., use `blockquote` for an "alert" component, or `button`
   for any interactive element)
2. **Copy the example component folder** to `src/components/<new_name>/`
3. **Keep or author preview coverage** by updating the copied `mocks.json` when
   the example includes one, or by authoring a new `mocks.json` if the new
   component needs named states beyond Workbench's built-in `Default` tab
4. **Modify** the copied files to implement the new component

When deciding whether to keep, remove, or author `mocks.json`, follow
`canvas-component-definition/references/component-mocks.md`.

This approach ensures consistent patterns for `component.yml` structure, JSX
conventions, and Workbench preview coverage across all components.

```bash
# Example: Create an Alert component based on Blockquote
cp -r examples/components/blockquote src/components/alert
```

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 examples, the imports will work
automatically.

After creating or visually modifying a component, leave it in a reviewable
Workbench state and use `nebula-component-validation` before considering the
task complete.

### Copying an existing example component

**Workflow for copying example components:**

1. **Check for existing example:** If the requested component (e.g., "hero")
   exists in `examples/components/`, plan to copy it directly.
2. **Analyze dependencies:** Read the example component's `index.jsx` file and
   identify all `@/components/<name>` imports. These are component dependencies.
3. **Recursively discover nested dependencies:** For each dependency found,
   check its `index.jsx` for additional `@/components/<name>` imports. Continue
   until all dependencies are discovered. For example, `hero` imports
   `two_column_text`, which imports `heading` and `text`.
4. **Check what already exists:** List the contents of `src/components/` to see
   which components are already present.
5. **Copy only missing components:** Copy only the example components (and their
   preview coverage, when included in the copied folders) that don't already
   exist in `src/components/`. Do NOT overwrite existing components.

**Example scenario:** User asks for a "hero" component.

```bash
# Step 1: Check existing components in src/
ls src/components/

# Suppose output shows only: button/  global.css

# Step 2: Analyze hero dependencies (hero → two_column_text → heading, text)
# Missing components: hero, two_column_text, heading, text
# button already exists, so skip it if it were a dependency

# Step 3: Copy all missing components in one batch
cp -r examples/components/hero src/components/
cp -r examples/components/two_column_text src/components/
cp -r examples/components/heading src/components/
cp -r examples/components/text src/components/
```

## Required component folder structure

**CRITICAL:** Every component folder in `src/components/` MUST contain exactly
two files:

```
src/components/<component-name>/
├── index.jsx      # React component implementation
└── component.yml  # Component metadata and props for Drupal Canvas
```

**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
`kebab-case` (with hyphens) for new and modified components in
`src/components/`.

**Legacy exception:** `examples/components/` may contain legacy `snake_case`
names. Keep those examples unchanged unless explicitly asked to migrate them.

After creating components, verify the folder structure:

```bash
# 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.

## Best practices

### Reuse existing components

**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.

If the component you need doesn't exist in `src/components/` yet, check if it
exists in `examples/components/`. If so, copy it to `src/components/` first (see
"Copying an Existing Example Component" above), then import and use it.

```jsx
// Correct
import Button from '@/components/button';

const NewsletterSignup = ({ onSubmit }) => (
  <form onSubmit={onSubmit}>
    <input type="email" placeholder="Enter your email" />
    <Button variant="primary">Subscribe</Button>
  </form>
);

// Wrong
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>
);
```

## Common pitfalls

- **Overwriting existing components** - Always check `src/components/` first
- **Missing dependencies** - Recursively check all `@/components/` imports
- **Incomplete component folder** - Both `index.jsx` and `component.yml` are
  required
- **Ignoring the `@/components` alias** - Use this import alias; it points to
  `src/components`

