@latte-macchiat-io/latte-payload
v1.0.3
Published
Reusable Payload CMS collections, utilities, and components for Latte projects
Maintainers
Readme
@latte-macchiat-io/latte-payload
Reusable Payload CMS collections, utilities, and components for Latte projects. This package provides a solid foundation for building Payload CMS applications with pre-configured collections, access control, email queuing, and more.
Features
- 5 Pre-built Collections: Users, Media, ContactMessages, EmailTemplates, QueuedEmails
- 2 Global Configs: PrivacyPolicy, TermsOfUse
- 8 Access Control Functions: Ready-to-use access control patterns
- Email System: Template-based emails with queue and retry logic
- Background Jobs: Async email processing with exponential backoff
- Admin UI Components: Custom components for better UX
- Fully Typed: Complete TypeScript support
- Configurable: All collections and utilities accept configuration options
Installation
pnpm add @latte-macchiat-io/latte-payloadPeer Dependencies
pnpm add payload @payloadcms/db-postgres @payloadcms/next @payloadcms/richtext-lexical react react-dom next sharpOptional Dependencies
# For email functionality
pnpm add @payloadcms/email-resend # or @payloadcms/email-nodemailer
# For S3 storage
pnpm add @payloadcms/storage-s3Quick Start
Basic Usage
// payload.config.ts
import { buildConfig } from 'payload';
import { postgresAdapter } from '@payloadcms/db-postgres';
import {
Users,
Media,
EmailTemplates,
QueuedEmails,
PrivacyPolicy,
TermsOfUse,
processEmailQueueTaskConfig
} from '@latte-macchiat-io/latte-payload';
export default buildConfig({
collections: [
Users,
Media,
EmailTemplates,
QueuedEmails,
// Add your custom collections here
],
globals: [
PrivacyPolicy,
TermsOfUse,
],
jobs: {
tasks: [processEmailQueueTaskConfig],
},
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI,
},
}),
// ... other config
});Collections
Users
Complete authentication system with email verification and password reset.
import { createUsersCollection } from '@latte-macchiat-io/latte-payload';
// Customize the Users collection
const CustomUsers = createUsersCollection({
roles: [
{ label: { fr: 'Admin', nl: 'Admin', en: 'Admin' }, value: 'admin' },
{ label: { fr: 'Éditeur', nl: 'Redacteur', en: 'Editor' }, value: 'editor' },
{ label: { fr: 'Utilisateur', nl: 'Gebruiker', en: 'User' }, value: 'user' },
],
defaultLocale: 'fr',
tokenExpiration: 60 * 60 * 24 * 7, // 1 week
verifyEmailConfig: {
generateVerifyUrl: async (token, user) => {
return `https://yourdomain.com/verify?token=${token}`;
},
},
});Media
File upload collection with S3 support.
import { Media } from '@latte-macchiat-io/latte-payload';
import { s3Storage } from '@payloadcms/storage-s3';
export default buildConfig({
collections: [Media],
plugins: [
s3Storage({
collections: {
media: true,
},
bucket: process.env.S3_BUCKET,
config: {
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
},
region: process.env.S3_REGION,
},
}),
],
});EmailTemplates
Manage email templates in the CMS.
import { createEmailTemplatesCollection } from '@latte-macchiat-io/latte-payload';
const CustomEmailTemplates = createEmailTemplatesCollection({
emailCodes: [
{ label: 'verify-email', value: 'verify-email' },
{ label: 'password-lost', value: 'password-lost' },
{ label: 'welcome', value: 'welcome' },
{ label: 'order-confirmation', value: 'order-confirmation' },
],
});QueuedEmails
Email queue with retry logic and admin UI.
import { QueuedEmails } from '@latte-macchiat-io/latte-payload';ContactMessages
Store contact form submissions.
import { createContactMessagesCollection } from '@latte-macchiat-io/latte-payload';
const CustomContactMessages = createContactMessagesCollection({
locales: ['en', 'fr', 'nl', 'de'],
emailNotificationConfig: {
contactEmail: '[email protected]',
subject: 'New Contact Form Submission',
},
});Globals
PrivacyPolicy & TermsOfUse
Localized legal content with Next.js cache revalidation.
import { PrivacyPolicy, TermsOfUse } from '@latte-macchiat-io/latte-payload';Access Control
8 pre-built access control patterns:
import {
anyone, // Public access
authenticated, // Authenticated users only
authenticatedFieldLevel, // Field-level authenticated access
admins, // Admin users only
adminsFieldLevel, // Field-level admin access
publicReadAuthenticatedAccess, // Public read, authenticated write
authenticatedAccessOnly, // All operations require auth
adminAccessOnly, // All operations require admin
} from '@latte-macchiat-io/latte-payload';
// Use in your custom collections
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
access: publicReadAuthenticatedAccess,
fields: [
{
name: 'sensitiveField',
type: 'text',
access: {
read: adminsFieldLevel,
update: adminsFieldLevel,
},
},
],
};Utilities
Queue Email
import { queueEmail } from '@latte-macchiat-io/latte-payload';
await queueEmail({
payload,
to: '[email protected]',
emailCode: 'welcome',
variables: {
name: 'John Doe',
url: 'https://yourdomain.com',
},
locale: 'en',
idempotencyKey: `welcome-${userId}`, // Prevent duplicates
});Generate Email HTML
import { generateEmailHtmlFromTemplate } from '@latte-macchiat-io/latte-payload';
const emailContent = await generateEmailHtmlFromTemplate({
payload,
emailCode: 'order-confirmation',
locale: 'fr',
variables: {
orderNumber: '#12345',
customerName: 'Jane Doe',
},
});Get Payload Client
import { getPayloadClient } from '@latte-macchiat-io/latte-payload';
import config from './payload.config';
const payload = await getPayloadClient(config);Background Tasks
Process Email Queue
Automatically process queued emails with retry logic.
import { createProcessEmailQueueTask } from '@latte-macchiat-io/latte-payload';
import * as Sentry from '@sentry/nextjs';
const emailTask = createProcessEmailQueueTask({
timezone: 'America/New_York',
maxEmailsPerRun: 50,
delayBetweenEmails: 500, // 0.5 seconds
defaultFromAddress: '[email protected]',
errorReporter: {
captureException: Sentry.captureException,
},
});
export default buildConfig({
jobs: {
tasks: [emailTask],
},
});Email HTML Template
Create an HTML email template at ./emails/template.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ emailSubject }}</title>
</head>
<body>
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
{{ emailContent }}
</div>
</body>
</html>The {{ emailContent }} placeholder will be replaced with your email template content.
Environment Variables
# Required
DATABASE_URI=postgresql://user:password@localhost:5432/dbname
PAYLOAD_SECRET=your-secret-key
# Email (choose one)
ENABLE_EMAILS_SENDING=true
RESEND_API_KEY=re_xxx # For production (Resend)
# OR
SMTP_HOST=localhost # For development (Mailpit/Nodemailer)
SMTP_PORT=1025
[email protected]
# Contact form
[email protected]
# S3 Storage (optional)
S3_ENDPOINT=https://s3.amazonaws.com
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=xxx
S3_SECRET_ACCESS_KEY=xxx
S3_BUCKET=your-bucket-nameTypeScript Types
import type {
Locale,
EmailTemplateCode,
QueuedEmailStatus,
UsersCollectionConfig,
ContactMessagesConfig,
EmailTemplatesConfig,
ProcessEmailQueueConfig,
} from '@latte-macchiat-io/latte-payload';Version Compatibility
- Payload CMS: ^3.64.0
- React: ^19.0.0
- Next.js: ^15.0.0
- Node.js: >=22.x
Contributing
This package is maintained by Latte Macchiat.io for internal use across projects. If you find bugs or have suggestions, please open an issue.
License
MIT
