npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

payload-forgeai

v0.12.0

Published

A plugin for Payload CMS to generate content with AI

Readme

Payload Forge AI

AI-powered field generation plugin for Payload CMS. Automatically generate field content using OpenAI, with support for context-aware generation based on other fields in your document.

Features

  • 🤖 AI-powered field generation using OpenAI
  • 🔗 Context-aware generation using other field values
  • 📝 Custom prompts per field
  • 🎯 Support for relationships, selects, and all field types
  • 🗂️ Nested field support with dot notation (e.g., meta.title)
  • ⚡ Simple integration with existing Payload collections

Installation

npm install payload-forgeai
# or
pnpm add payload-forgeai
# or
yarn add payload-forgeai

Environment Variables

Create a .env file in your project root:

OPENAI_API_KEY=your_openai_api_key_here

# Optional: Enable debug logging
# PAYLOAD_FORGEAI_DEBUG=true

Configuration

Add the plugin to your payload.config.ts:

import { payloadForgeAi } from 'payload-forgeai'

export default buildConfig({
  plugins: [
    payloadForgeAi({
      apiKey: process.env.OPENAI_API_KEY,
      collections: {
        posts: {
          fields: [
            {
              name: 'title',
              prompt: 'Write a compelling title for this blog post',
            },
            {
              name: 'content',
              context: ['title', 'category'],
              prompt: 'Write engaging content for this blog post',
            },
          ],
        },
      },
    }),
  ],
})

Usage

Basic Field Generation

Configure a field for AI generation:

{
  name: 'title',
  prompt: 'Write a catchy title that is max 60 characters',
}

The plugin automatically includes the current field value in the context, instructing the AI to generate something different when regenerating. This is useful for getting variations.

To disable this behavior and allow the AI to consider the current value without the "generate different" instruction:

{
  name: 'title',
  prompt: 'Write a catchy title that is max 60 characters',
  generateDifferent: false, // AI can generate similar content
}

Nested Fields

The plugin supports fields at any level of nesting using dot notation:

payloadForgeAi({
  apiKey: process.env.OPENAI_API_KEY,
  collections: {
    articles: {
      fields: [
        {
          name: 'meta.title',  // Field inside a 'meta' group
          prompt: 'Write an SEO-optimized title',
        },
        {
          name: 'meta.description',
          context: ['meta.title', 'content'],
          prompt: 'Write a meta description',
        },
      ],
    },
  },
})

This works with:

  • Group fields: meta.title
  • Tabs: content.main.heading
  • Collapsible fields: advanced.settings.value

Context-Aware Generation

Use other fields as context for more relevant AI generation:

Simple Context (by field name)

{
  name: 'content',
  context: ['title', 'category'],
  prompt: 'Write the main content for this article',
}

Custom Context Prompts

Provide custom prompts for how each context field should be used:

{
  name: 'content',
  context: [
    {
      field: 'title',
      prompt: 'The article title is',
    },
    {
      field: 'category',
      prompt: 'The category for this post is',
    },
    {
      field: 'author',
      prompt: 'Written by author',
    },
  ],
  prompt: 'Write engaging content based on the context above',
}

Working with Relationships

The plugin automatically fetches and populates relationship fields:

// In your collection
fields: [
  {
    name: 'author',
    type: 'relationship',
    relationTo: 'users',
  },
  {
    name: 'bio',
    type: 'textarea',
  },
]

// In your AI config - Use full author object
{
  name: 'bio',
  context: [
    {
      field: 'author',
      prompt: 'Author details',
    },
  ],
  prompt: 'Write a professional bio',
}

// Or extract specific fields from the relationship
{
  name: 'bio',
  context: [
    {
      field: 'author',
      fields: ['name', 'email'], // Only include name and email
      prompt: 'Author details',
    },
  ],
  prompt: 'Write a professional bio and mention the author name',
}

// Use nested prompts - BOTH outer and inner prompts are used
{
  name: 'content',
  context: [
    {
      field: 'author',
      prompt: 'The author information', // Outer prompt - used as header
      fields: [
        {
          field: 'name',
          prompt: 'Written by', // Inner prompt - used for this specific field
        },
        {
          field: 'email',
          prompt: 'Contact', // Inner prompt - used for this specific field
        },
      ],
    },
  ],
  prompt: 'Write content with author attribution',
}
// AI receives:
// The author information:
//   Written by: John Doe
//   Contact: [email protected]

Selecting Specific Fields

Use the fields array to extract only specific properties from context:

{
  name: 'summary',
  context: [
    {
      field: 'author',
      fields: ['name'], // Only include the author's name
      prompt: 'Written by',
    },
    {
      field: 'metadata',
      fields: ['tags', 'category'], // Extract specific nested properties
    },
  ],
  prompt: 'Write a summary with author attribution',
}

Nested Field Selection

For complex nested objects, you can use recursive field configuration with prompts at each level:

{
  name: 'description',
  context: [
    {
      field: 'product',
      prompt: 'Product details', // Outer prompt (used as fallback for nested fields without prompts)
      fields: [
        'name', // Will use: "Product details - name: value"
        'price',
        {
          field: 'manufacturer',
          prompt: 'Made by', // This prompt overrides the parent
          fields: ['name', 'country'], // Will use: "Made by - name: value" and "Made by - country: value"
        },
        {
          field: 'specs',
          fields: [
            {
              field: 'weight',
              prompt: 'Product weight', // Custom prompt for this specific field
            },
          ],
        },
      ],
    },
  ],
  prompt: 'Write a product description',
}

How nested prompts work:

  • ALL prompts are used - both outer and nested prompts are included in the context
  • Outer prompts act as section headers/introductions
  • Nested prompts describe individual fields
  • Example output:
    Product details:
      name: Widget X
      Made by:
        name: ACME Corp
        country: USA
      Product weight: 2.5kg
  • This allows fine-grained control over how each piece of data is presented to the AI

Configuration Options

Plugin Options

type PayloadForgeAiConfig = {
  apiKey: string // Your OpenAI API key
  disabled?: boolean // Disable the plugin
  collections?: {
    [collectionSlug: string]: {
      fields: PayloadForgeAiFieldConfig[]
    }
  }
}

Field Configuration

type PayloadForgeAiContextField =
  | string // Simple field name
  | {
      field: string // Field name to use as context
      prompt?: string // Custom prompt for this context field
      fields?: PayloadForgeAiContextField[] // Recursively extract nested fields
    }

type PayloadForgeAiFieldConfig = {
  name: string // Field name to enable AI generation
  prompt: string // Instructions for the AI
  context?: PayloadForgeAiContextField[] // Fields to use as context
  generateDifferent?: boolean // If true (default), instructs AI to generate different from current value
}

Examples

Blog Post with Category and Author Context

payloadForgeAi({
  apiKey: process.env.OPENAI_API_KEY,
  collections: {
    posts: {
      fields: [
        {
          name: 'title',
          context: ['category'],
          prompt: 'Write a title (max 8 words)',
        },
        {
          name: 'excerpt',
          context: ['title', 'category'],
          prompt: 'Write a brief excerpt (max 150 characters)',
        },
        {
          name: 'content',
          context: [
            { field: 'title', prompt: 'Article title' },
            { field: 'category', prompt: 'Category' },
            { field: 'excerpt', prompt: 'Summary' },
            {
              field: 'author',
              fields: ['name'], // Only use author's name
              prompt: 'Written by',
            },
          ],
          prompt:
            'Write comprehensive content (300-500 words) and include author attribution at the end',
        },
      ],
    },
  },
})

Product Description with Related Data

payloadForgeAi({
  apiKey: process.env.OPENAI_API_KEY,
  collections: {
    products: {
      fields: [
        {
          name: 'description',
          context: [
            { field: 'name', prompt: 'Product name' },
            { field: 'category', prompt: 'Category' },
            { field: 'price', prompt: 'Price' },
            { field: 'features', prompt: 'Key features' },
          ],
          prompt: 'Write a compelling product description',
        },
        {
          name: 'seoTitle',
          context: ['name', 'category'],
          prompt: 'Write an SEO-optimized title (max 60 chars)',
        },
        {
          name: 'seoDescription',
          context: ['name', 'description'],
          prompt: 'Write an SEO meta description (max 160 chars)',
        },
      ],
    },
  },
})

Environment Variables

Create a .env file in your project:

OPENAI_API_KEY=your_openai_api_key_here

How It Works

  1. The plugin adds a "Generate" button to configured fields in the Payload admin UI
  2. When clicked, it gathers context from other fields in the document
  3. Includes the current field value (if any) and instructs the AI to generate something different (configurable)
  4. Sends the context and prompt to OpenAI via your API endpoint
  5. Returns the generated content and populates the field

Development

Running the Dev Environment

# Install dependencies
pnpm install

# Create .env file
cp .env.example .env

# Add your OpenAI API key to .env
# OPENAI_API_KEY=your_key_here

# Start the dev server
pnpm dev

Testing

pnpm test

Debugging

If you're experiencing issues with field path resolution or nested fields not being found, you can enable debug logging:

# Add to your .env file
PAYLOAD_FORGEAI_DEBUG=true

This will log detailed information about:

  • Field path searches
  • Which fields are being checked
  • Container field traversal (collapsible, tabs, groups)
  • Field resolution success/failure

The debug logs will appear in your server console when the plugin initializes and when validating field configurations.

License

MIT

Support

For issues and questions, please open an issue on GitHub.