smithery.ai

puck-component

Create new Puck page builder components for the NodeHive Next.js starter.

First seen Mar 24, 2026

Installation

$ npx skills add https://smithery.ai

Summary

  • Create new Puck page builder components for the NodeHive Next.js starter.
  • Use when asked to add, create, or build a new Puck component, visual editor component, or page builder block.
  • Covers the full workflow - React component, Puck config, registration, and editor UI integration.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,058 B
  • docs SUMMARY.md 303 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Puck Component Creation

Create Puck page builder components following established patterns in this codebase.

File Structure

Every Puck component has 3 files in src/components/theme/{category}/{component-name}/:

{component-name}/
├── {component-name}.tsx          # React component
├── {component-name}.config.tsx   # Puck configuration
└── {component-name}.stories.tsx  # Storybook stories (optional)

Categories:

  • atoms-content/ - Content primitives (Heading, BodyCopy, Image, Video)
  • atoms-layout/ - Layout primitives (Container, Grid, TwoColumns, Space)
  • organisms/ - Composed components (Card, Statistics)
  • sections/ - Full-width sections (Hero)

Step 1: Create React Component

import React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const myComponentVariants = cva('base-classes', {
  variants: {
    size: {
      sm: 'text-sm',
      md: 'text-base',
      lg: 'text-lg',
    },
  },
  defaultVariants: {
    size: 'md',
  },
});

export interface MyComponentProps
  extends React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof myComponentVariants> {
  title?: string;
}

const MyComponent: React.FC<MyComponentProps> = ({
  title,
  size,
  className,
  ...props
}) => {
  return (
    <div className={cn(myComponentVariants({ size }), className)} {...props}>
      {title && <h3>{title}</h3>}
    </div>
  );
};

export default MyComponent;

Key patterns:

  • Use CVA for variants
  • Extend React.HTMLAttributes<HTMLElement>
  • Use cn() from @/lib/utils for class merging

Step 2: Create Puck Config

import { ComponentConfig } from '@puckeditor/core';
import MyComponent from './my-component';

export const MyComponentConfig: ComponentConfig = {
  label: 'My Component',
  fields: {
    title: { type: 'text', label: 'Title' },
    size: {
      type: 'select',
      label: 'Size',
      options: [
        { label: 'Small', value: 'sm' },
        { label: 'Medium', value: 'md' },
        { label: 'Large', value: 'lg' },
      ],
    },
  },
  defaultProps: {
    title: 'Default Title',
    size: 'md',
  },
  render: ({ title, size }) => <MyComponent title={title} size={size} />,
};

For built-in field types, see [references/field-types.md](references/field-types.md).

Step 3: Register in Puck Config

Edit src/components/drupal/node/puck-page/puck.page.config.tsx:

import { MyComponentConfig } from '@/components/theme/{category}/my-component/my-component.config';

export const config: Config = {
  categories: {
    content: {
      components: ['Heading', 'MyComponent'], // Add to category
    },
  },
  components: {
    MyComponent: MyComponentConfig, // Register component
  },
};

Step 4: Add Icon and Label

Edit src/components/puck/editor/component-item.tsx:

import { MyIcon } from 'lucide-react';

const COMPONENT_ICONS: Record<string, React.ReactNode> = {
  MyComponent: <MyIcon className="size-4" />,
};

const COMPONENT_LABELS: Record<string, string> = {
  MyComponent: 'My Component',
};

Array Fields

For repeating items:

items: {
  type: 'array',
  label: 'Items',
  max: 5,
  arrayFields: {
    title: { type: 'text', label: 'Title' },
    description: { type: 'textarea', label: 'Description' },
  },
},

Slot Fields (Layout Components)

For nesting other components:

fields: {
  content: { type: 'slot' },
},
render: ({ content: Content }) => (
  <div>
    <Content />
  </div>
),

References

  • [Field Types Reference](references/field-types.md) - Built-in and custom field types
  • Puck Documentation - Official Puck docs