@ducksauce/payload-plugin
v2.0.0
Published
A comprehensive Payload CMS plugin that provides collections, globals, blocks, and admin panel enhancements for building content management systems with the Ducksauce design system.
Readme
@ducksauce/payload-plugin
A comprehensive Payload CMS plugin that provides collections, globals, blocks, and admin panel enhancements for building content management systems with the Ducksauce design system.
🚀 Quick Start
Installation
npm install @ducksauce/payload-plugin
# or
yarn add @ducksauce/payload-plugin
# or
pnpm add @ducksauce/payload-pluginUsage
import { buildConfig } from "payload/config";
import { ducksauce } from "@ducksauce/payload-plugin";
export default buildConfig({
plugins: [
ducksauce({
prefix: "ds_",
features: {
blog: true,
heroBlocks: true,
menus: true,
analytics: false,
customDomain: false,
},
}),
],
// ... rest of config
});🎯 Features
Collections
- Blog Posts - Complete blog system with authors, categories, and SEO
- Pages - Flexible page builder with blocks
- Media - File management with image optimization
- Categories - Hierarchical categorization system
- Users - User management with roles and permissions
Globals
- Header - Site header configuration with navigation
- Footer - Site footer configuration with links
- SEO - Global SEO settings and meta tags
Blocks
- Hero Block - Eye-catching hero sections with CTA buttons
- Content Block - Rich text content with formatting
- Image Block - Image galleries and featured images
- Quote Block - Testimonials and quotes
- CTA Block - Call-to-action sections
Admin Enhancements
- Custom Styling - Ducksauce design system integration
- Improved UX - Better admin panel experience
- Feature Flags - Enable/disable features based on entitlements
⚙️ Configuration
Plugin Options
interface DucksauceOptions {
prefix?: string; // Collection prefix (default: 'ds_')
features?: {
blog?: boolean; // Enable blog functionality
heroBlocks?: boolean; // Enable hero blocks
menus?: boolean; // Enable menu management
analytics?: boolean; // Enable analytics features
customDomain?: boolean; // Enable custom domain features
};
collections?: {
posts?: CollectionConfig; // Custom posts collection
pages?: CollectionConfig; // Custom pages collection
media?: CollectionConfig; // Custom media collection
};
globals?: {
header?: GlobalConfig; // Custom header global
footer?: GlobalConfig; // Custom footer global
};
}Basic Configuration
import { buildConfig } from "payload/config";
import { ducksauce } from "@ducksauce/payload-plugin";
export default buildConfig({
plugins: [
ducksauce({
prefix: "ds_",
features: {
blog: true,
heroBlocks: true,
menus: true,
},
}),
],
collections: [
// Your custom collections
],
globals: [
// Your custom globals
],
});Advanced Configuration
import { buildConfig } from "payload/config";
import { ducksauce } from "@ducksauce/payload-plugin";
export default buildConfig({
plugins: [
ducksauce({
prefix: "ds_",
features: {
blog: true,
heroBlocks: true,
menus: true,
analytics: true,
customDomain: true,
},
collections: {
posts: {
// Override default posts collection
fields: [
// Custom fields
],
},
},
globals: {
header: {
// Override default header global
fields: [
// Custom fields
],
},
},
}),
],
});📝 Collections
Posts Collection
Blog posts with authors, categories, and SEO features.
// Default fields
{
title: 'text',
slug: 'text',
author: 'relationship',
publishedDate: 'date',
category: 'relationship',
excerpt: 'textarea',
content: 'richText',
featuredImage: 'upload',
seo: 'group',
status: 'select',
}Pages Collection
Flexible pages with block-based content.
// Default fields
{
title: 'text',
slug: 'text',
layout: 'blocks',
seo: 'group',
status: 'select',
}Media Collection
File management with image optimization.
// Default fields
{
filename: 'text',
alt: 'text',
caption: 'text',
mimeType: 'text',
filesize: 'number',
width: 'number',
height: 'number',
}🌐 Globals
Header Global
Site header configuration with navigation.
// Default fields
{
logo: 'upload',
navigation: 'array',
cta: 'group',
}Footer Global
Site footer configuration with links.
// Default fields
{
logo: 'upload',
navigation: 'array',
social: 'array',
copyright: 'text',
}🧱 Blocks
Hero Block
Eye-catching hero sections with CTA buttons.
// Block fields
{
title: 'text',
subtitle: 'text',
background: 'upload',
cta: 'group',
alignment: 'select',
}Content Block
Rich text content with formatting.
// Block fields
{
content: 'richText',
width: 'select',
padding: 'select',
}Image Block
Image galleries and featured images.
// Block fields
{
image: 'upload',
caption: 'text',
alignment: 'select',
size: 'select',
}🎨 Admin Styling
The plugin includes custom admin panel styling that integrates with the Ducksauce design system.
CSS Variables
:root {
--ds-admin-bg: #0b0b0c;
--ds-admin-fg: #fff;
--ds-admin-accent: #6ee7b7;
--ds-admin-border: #374151;
}Custom Components
The plugin provides custom admin components for better UX:
- Enhanced Media Library - Better file management
- Block Editor - Improved block editing experience
- SEO Preview - Live SEO preview in admin
- Analytics Dashboard - Built-in analytics (if enabled)
🛠️ Development
Prerequisites
- Node.js 18.20.2 or >=20.9.0
- pnpm 10.13.1+
- Payload CMS 3.x
Setup
# Install dependencies
pnpm install
# Start development mode
pnpm dev
# Build for production
pnpm build
# Run linting
pnpm lint
# Clean build artifacts
pnpm cleanProject Structure
packages/payload-plugin/
├── src/
│ ├── index.ts # Main plugin export
│ ├── lib/
│ │ ├── collections.ts # Collection definitions
│ │ ├── globals.ts # Global definitions
│ │ └── blocks.ts # Block definitions
│ ├── blocks/
│ │ └── Hero.ts # Hero block component
│ └── styles/
│ └── admin.css # Admin panel styles
├── package.json
├── tsconfig.json
└── README.mdAdding New Collections
- Create collection file in
src/lib/collections/ - Export from
src/lib/collections.ts - Add to plugin configuration
- Update this README
Example Collection
// src/lib/collections/Example.ts
import type { CollectionConfig } from "payload";
export const Example: CollectionConfig = {
slug: "examples",
admin: {
useAsTitle: "title",
group: "Content",
},
access: {
read: () => true,
},
fields: [
{
name: "title",
type: "text",
required: true,
},
{
name: "content",
type: "richText",
},
],
};📦 Building
Development Build
pnpm devThis starts tsup in watch mode, rebuilding on file changes.
Production Build
pnpm buildThis creates:
dist/index.js- Main plugin exportdist/index.d.ts- TypeScript declarations
Build Configuration
The package uses tsup for building:
{
"build": "tsup src/index.ts --dts --format esm --external payload --external react --external react-dom"
}🧪 Testing
# Run tests
pnpm test
# Run tests in watch mode
pnpm test --watch
# Run tests with coverage
pnpm test --coverage📦 Publishing
Versioning
This package uses Changesets for versioning:
- Create a changeset:
pnpm changeset - Version the package:
pnpm release - Publish:
pnpm release(includes publishing)
Manual Publishing
# Build the package
pnpm build
# Publish to npm
pnpm publishPackage Configuration
{
"name": "@ducksauce/payload-plugin",
"version": "0.0.0",
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"sideEffects": false,
"files": ["dist", "styles"],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}🔗 Dependencies
Peer Dependencies
payload^3.0.0react^18 || ^19react-dom^18 || ^19
Dev Dependencies
@types/node- Node.js TypeScript types@types/react- React TypeScript types@types/react-dom- React DOM TypeScript typeseslint- Code lintingtsup- TypeScript bundlertypescript- TypeScript compiler
📚 API Reference
ducksauce
Main plugin function that returns a Payload CMS plugin.
Parameters
options: DucksauceOptions- Plugin configuration options
Returns
Plugin- Payload CMS plugin
DucksauceOptions
Plugin configuration interface.
Properties
prefix?: string- Collection prefixfeatures?: DucksauceFeatures- Feature flagscollections?: DucksauceCollections- Custom collectionsglobals?: DucksauceGlobals- Custom globals
DucksauceFeatures
Feature flags interface.
Properties
blog?: boolean- Enable blog functionalityheroBlocks?: boolean- Enable hero blocksmenus?: boolean- Enable menu managementanalytics?: boolean- Enable analytics featurescustomDomain?: boolean- Enable custom domain features
🔐 Entitlements Integration
The plugin integrates with the Ducksauce entitlements system to enable/disable features based on user subscriptions.
Feature Checking
import { hasEntitlement } from "@ducksauce/payload-plugin";
// Check if user has access to a feature
const hasBlogAccess = await hasEntitlement(userId, "blog");
const hasAnalyticsAccess = await hasEntitlement(userId, "analytics");Conditional Features
Features can be conditionally enabled based on entitlements:
ducksauce({
features: {
blog: true, // Always enabled
analytics: false, // Disabled by default, enabled via entitlements
},
});🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Create a changeset
- Submit a pull request
📄 License
This package is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
- Documentation: This README
- Issues: Create an issue in the repository
- Discussions: Use GitHub Discussions for questions
Built with ❤️ using Payload CMS and React.
