Back to list
NETNODEAG

puck-component

by NETNODEAG

Official NodeHive NextJS Minimal Starter Template

6🍴 0📅 Jan 19, 2026

SKILL.md


name: puck-component description: "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."

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.

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

Score

Total Score

50/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon