Skip to content

delmaredigital/payload-puck

Repository files navigation

@delmaredigital/payload-puck

A PayloadCMS plugin for integrating Puck visual page builder. Build pages visually with drag-and-drop components while leveraging Payload's content management capabilities.

Live Demo - Try It Now    Starter Template - Use This

Deploy with Vercel


Documentation

Full documentation →

Ask DeepWiki

Covers installation, configuration, components, custom fields, theming, layouts, dark mode, page-tree integration, hybrid integration, AI integration, and more.


Install

pnpm add @delmaredigital/payload-puck @puckeditor/core

Requirements

Dependency Version
@puckeditor/core >= 0.21.0
payload >= 3.69.0
@payloadcms/next >= 3.69.0
next >= 15.4.8
react >= 19.2.1

Note: Puck 0.21+ moved from @measured/puck to @puckeditor/core. This plugin requires the new package scope.


Quick Start

1. Add the Plugin

// src/payload.config.ts
import { buildConfig } from 'payload'
import { createPuckPlugin } from '@delmaredigital/payload-puck/plugin'

export default buildConfig({
  plugins: [
    createPuckPlugin({
      pagesCollection: 'pages',
    }),
  ],
})

2. Provide Puck Configuration

// app/(app)/layout.tsx
import { PuckConfigProvider } from '@delmaredigital/payload-puck/client'
import { editorConfig } from '@delmaredigital/payload-puck/config/editor'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <PuckConfigProvider config={editorConfig}>
          {children}
        </PuckConfigProvider>
      </body>
    </html>
  )
}

3. Create a Frontend Route

// app/(frontend)/[[...slug]]/page.tsx
import { getPayload } from 'payload'
import config from '@payload-config'
import { PageRenderer } from '@delmaredigital/payload-puck/render'
import { baseConfig } from '@delmaredigital/payload-puck/config'
import { notFound } from 'next/navigation'

async function getPage(slug?: string[]) {
  const payload = await getPayload({ config })
  const slugPath = slug?.join('/') || ''
  const { docs } = await payload.find({
    collection: 'pages',
    where: {
      and: [
        { _status: { equals: 'published' } },
        slugPath
          ? { slug: { equals: slugPath } }
          : { isHomepage: { equals: true } },
      ],
    },
    limit: 1,
  })
  return docs[0] || null
}

export default async function Page({ params }: { params: Promise<{ slug?: string[] }> }) {
  const { slug } = await params
  const page = await getPage(slug)
  if (!page) notFound()
  return <PageRenderer config={baseConfig} data={page.puckData} />
}

That's it! The plugin registers the editor view, API endpoints, and "Edit with Puck" buttons automatically.


Documentation

For everything else — components, custom fields, theming, layouts, dark mode, page-tree integration, hybrid integration, AI integration, advanced configuration, and the full export reference — see the full documentation.


License

MIT

Contributors

Languages