AI page generation
Let editors describe a page in plain language and have Puck AI build it from your components.
The plugin integrates Puck AI so editors can describe what they want in natural language and have the AI build the page layout from your components.
Early preview
Puck's AI features are capable, but this plugin's integration is still early and under active development. Expect changes as it is refined.
Requirements
- A
PUCK_API_KEYenvironment variable, from Puck Cloud. @puckeditor/plugin-aiand@puckeditor/cloud-client, which ship with the plugin.zod, if you define custom tools.
Quick start
Enable AI in the plugin configuration:
createPuckPlugin({
pagesCollection: 'pages',
ai: {
enabled: true,
context: 'We are Acme Corp, a B2B SaaS company. Use professional language.',
},
})This registers the AI chat endpoint at /api/puck/ai, adds the AI chat plugin to the editor, and applies detailed instructions for every built-in component to improve what the AI generates.
Business context from the admin
Instead of hard-coding context, manage it in Payload:
createPuckPlugin({
ai: {
enabled: true,
contextCollection: true, // Creates the puck-ai-context collection
},
})This creates a puck-ai-context collection where you add entries for brand guidelines, tone of voice, product information, industry context, technical requirements and page patterns. Entries can be enabled, disabled and ordered. A Context panel in the Puck plugin rail lets editors view, create, edit and toggle entries without leaving the editor.
Prompts
Store reusable prompts in Payload:
createPuckPlugin({
ai: {
enabled: true,
promptsCollection: true, // Creates the puck-ai-prompts collection
examplePrompts: [
{ label: 'Landing page', prompt: 'Create a landing page for...' },
],
},
})Prompts from the collection appear in the AI chat, and a Prompts panel in the plugin rail manages them in the editor. examplePrompts adds static prompts alongside them.
Custom tools
Tools let the AI query your data while it builds a page:
import { z } from 'zod'
createPuckPlugin({
ai: {
enabled: true,
tools: {
getProducts: {
description: 'Get products from the database',
inputSchema: z.object({ category: z.string() }),
mode: 'preload',
execute: async ({ category }, { payload }) => {
return await payload.find({
collection: 'products',
where: { category: { equals: category } },
})
},
},
},
},
})Prop
Type
/ai also exports createTool() and createPayloadTools() for building tools.
Usage tracking
onFinish runs after each generation with its cost and token usage:
createPuckPlugin({
ai: {
enabled: true,
onFinish: ({ totalCost, tokenUsage }) => {
console.log(`Cost: $${totalCost}`)
console.log(`Tokens: ${tokenUsage.totalTokens}`)
// tokenUsage also includes: inputTokens, outputTokens,
// reasoningTokens, cachedInputTokens
},
},
})Modifying requests
On a PuckEditor you render yourself, aiOptions.prepareRequest changes outgoing AI requests before they are sent:
<PuckEditor
enableAi={true}
aiOptions={{
prepareRequest: (opts) => ({
...opts,
headers: { ...opts.headers, 'X-Tenant-ID': tenantId },
}),
scrollTracking: true,
}}
/>aiOptions also takes host (default '/api/puck/ai') and examplePrompts. scrollTracking (default true) makes the editor follow new content as it streams in.
AI options
Prop
Type
Component instructions
The plugin includes instructions for every built-in component. To customise or extend them:
createPuckPlugin({
ai: {
enabled: true,
componentInstructions: {
Heading: {
ai: { instructions: 'Use our brand voice: professional but approachable' },
fields: {
text: {
ai: {
instructions: 'Keep under 8 words',
stream: true,
},
},
},
},
// Exclude a component from AI generation entirely
InternalWidget: {
ai: { exclude: true },
},
// Configure default zone behaviour
Section: {
ai: {
defaultZone: {
allow: ['Text', 'Heading', 'Button'],
disallow: ['Section'],
},
},
},
},
},
})- Component-level options:
instructions,exclude,defaultZone(withallow,disallow,disabled), andschema. - Field-level options:
instructions,required,exclude,schema,stream(stream the value during generation) andbind(the name of a tool whose result fills the field deterministically).
Standalone API route
For a custom setup outside the plugin's endpoints, build the AI route yourself. Authenticate with payload.auth(), as for the other route factories:
import { createPuckAiApiRoutes } from '@delmaredigital/payload-puck/ai'
import { getPayload } from 'payload'
import config from '@payload-config'
export const { POST } = createPuckAiApiRoutes({
payloadConfig: config,
auth: {
authenticate: async (request) => {
const payload = await getPayload({ config })
const { user } = await payload.auth({ headers: request.headers })
if (!user) return { authenticated: false }
return { authenticated: true, user }
},
},
ai: {
context: 'Your business context...',
},
})ai here also takes tools, apiKey (defaults to PUCK_API_KEY), host and onFinish. createPromptApiRoutes and createPromptApiRoutesWithId build the prompt routes the same way.
AI exports
import {
// Plugins
createAiPlugin,
createPromptEditorPlugin,
createContextEditorPlugin,
// Hooks
useAiPrompts,
useAiContext,
// Config utilities
injectAiConfig,
comprehensiveComponentAiConfig,
pagePatternSystemContext,
// API routes
createPuckAiApiRoutes,
createPromptApiRoutes,
createPromptApiRoutesWithId,
createAiGenerate,
// Tools
createTool,
createPayloadTools,
} from '@delmaredigital/payload-puck/ai'
