payload-plugin-newsletter
Version:
Complete newsletter management plugin for Payload CMS with subscriber management, magic link authentication, and email service integration
1,059 lines (860 loc) • 69.5 kB
Markdown
## [0.25.9] - 2025-08-19
### Fixed
- Fixed providerId/externalId not being saved during broadcast creation
- Moved provider creation from create to update operation
- Provider broadcast is now created on first update when subject and content are present
- Ensures IDs are properly persisted to the database
- Prevents issues with Payload's create operation not persisting afterChange modifications
### Changed
- Broadcasts are now created in Payload first, then synced to provider on first meaningful update
- More robust approach that works with Payload's hook lifecycle
## [0.25.8] - 2025-08-19
### Fixed
- Added check to prevent double broadcast creation if externalId/providerId already exists
- Enhanced logging to show document status and existing IDs during creation
- Added logging for GET broadcast response to diagnose sync issues
- Helps identify root cause of duplicate broadcast creation
### Changed
- More descriptive hook logging to distinguish between sync and publish hooks
## [0.25.7] - 2025-08-19
### Fixed
- Fixed TypeScript type errors in error handling code
- Resolved all linting errors (warnings remain but don't block the build)
- Simplified error logging to avoid type conversion issues
## [0.25.6] - 2025-08-19
### Changed
- Enhanced error logging for Broadcast API provider to diagnose connection issues
- Added detailed response logging for successful and failed API calls
- Improved error messages to show actual API responses
- Added logging for GET requests after broadcast creation
- Better JSON parsing error handling with response body details
## [0.25.5] - 2025-08-18
### Fixed
- Fixed "document not found" error when creating broadcasts by removing unnecessary update call during creation
- The afterChange hook now properly returns the modified document instead of trying to update it
- Added debug logging to help diagnose provider sync issues
- Ensures smooth broadcast creation without transaction conflicts
## [0.25.4] - 2025-08-18
### Fixed
- Fixed External ID not being populated when creating broadcasts, preventing webhook updates from syncing
- Both `providerId` and `externalId` are now set when creating broadcasts in the provider
- Webhooks can now properly find and update broadcasts by External ID
- Ensures full bidirectional sync between Payload CMS and Broadcast software
## [0.25.3] - 2025-08-16
### Added
- Media population support for upload nodes within rich text fields in custom blocks
- Rich text fields in custom blocks now properly populate nested image uploads for email rendering
### Fixed
- Images inserted in rich text editors within custom blocks now render correctly in email previews
## [0.25.2] - 2025-08-15
### Fixed
- Fixed issue where editing draft broadcasts created duplicate entries in the provider instead of updating the existing broadcast
- Broadcasts now immediately sync to provider on creation with minimal data to establish the association
## [0.25.1] - 2025-08-09
### Fixed
- **Removed webhook status updates**: Eliminated permission errors when processing Broadcast webhooks
- Webhook handler no longer attempts to update global settings
- Fixes "Only administrators can modify newsletter settings" errors
### Changed
- **Webhook subscribers now start as active**: `subscriber.created` webhook events now set status as 'active' instead of 'pending'
- Better aligns with single opt-in workflows
- Matches Broadcast's confirmed subscriber status
- Welcome emails still prevented by `importedFromProvider` flag
## [0.25.0] - 2025-08-08
### Changed
- **Improved welcome email behavior**: Plugin now properly handles all subscription scenarios
- New signups via frontend: Send welcome email ✓
- Resubscriptions via frontend: Send welcome email ✓
- Webhook imports (new subscribers): No welcome email ✓
- Webhook reactivations: No welcome email ✓
- **Resubscription support**: Users who resubscribe through the frontend now receive a "Welcome back" email
- **Better UX**: Welcome emails now check the `importedFromProvider` flag by default
### Fixed
- Fixed missing welcome emails for user-initiated resubscriptions
- Fixed unwanted welcome emails for webhook-imported subscribers
## [0.24.0] - 2025-08-08
### Added
- **Skip welcome email for webhook imports**: Added `importedFromProvider` field to subscribers
- Set to `true` for all subscribers created via webhook events
- Allows projects to skip welcome emails for bulk imports from Broadcast
- Field is read-only in admin UI to prevent accidental changes
## [0.23.0] - 2025-08-07
### Added
- **Complete webhook sync for Broadcast subscribers**: Added support for three new webhook events
- `subscriber.created`: Syncs new subscribers created in Broadcast interface to Payload
- `subscriber.updated`: Syncs subscriber updates from Broadcast to Payload
- `subscriber.deleted`: Removes subscribers from Payload when deleted in Broadcast
- **Bidirectional sync**: Now provides complete two-way synchronization between Broadcast and Payload
### Changed
- Enhanced webhook event handling to support all subscriber lifecycle events
- Improved logging for better webhook debugging
## [0.22.0] - 2025-08-07
### Changed
- **Improved Broadcast sync**: Now uses proper subscribe/unsubscribe endpoints
- Uses `/api/v1/subscribers/unsubscribe.json` for unsubscribing (sets `unsubscribed_at` timestamp)
- Uses `/api/v1/subscribers.json` for both new subscriptions and resubscriptions
- Removed language tagging as per user preference
- Simplified resubscription flow - no special error handling needed
- **Better compliance tracking**: Broadcast now properly tracks unsubscribe timestamps for compliance
### Fixed
- Fixed Broadcast provider to properly handle subscription status changes
- Removed unnecessary contact existence checks (Broadcast API handles this gracefully)
## [0.21.4] - 2025-08-07
### Fixed
- Fixed ESLint error by prefixing unused webhookId variable with underscore
## [0.21.3] - 2025-08-06
### Fixed
- Fixed webhook authentication by using correct Broadcast header names
- Changed from `x-broadcast-signature` to `broadcast-webhook-signature`
- Changed from `x-broadcast-timestamp` to `broadcast-webhook-timestamp`
- Added support for optional `broadcast-webhook-id` header
- Added timestamp validation to prevent replay attacks (5 minute window)
- Headers now match Broadcast's actual webhook implementation
## [0.21.2] - 2025-08-06
### Fixed
- Fixed webhook endpoint paths to include `/newsletter` prefix for proper API routing
- Changed `/webhooks/broadcast` to `/newsletter/webhooks/broadcast`
- Changed `/webhooks/verify` to `/newsletter/webhooks/verify`
- This ensures webhooks work correctly with Payload's API routing
## [0.21.1] - 2025-08-06
### Fixed
- Fixed TypeScript and ESLint errors in webhook implementation
- Removed unused import (BroadcastQueueingEvent)
- Fixed unused parameter warnings with underscore prefix
- Added block scopes to switch cases for ESLint compliance
- Fixed unused error variable in catch blocks
## [0.21.0] - 2025-01-31
### Added
- **Webhook Support**: Real-time webhook integration for Broadcast provider
- Automatic updates for subscriber events (subscribed/unsubscribed)
- Real-time broadcast status updates (scheduled, in_progress, sent, etc.)
- HMAC-SHA256 signature verification for security
- Webhook configuration UI in Newsletter Settings
- Manual webhook registration with setup instructions
### Changed
- **BREAKING**: Removed polling-based unsubscribe synchronization
- Webhooks now provide real-time updates instead of scheduled polling
- Removed `unsubscribeSync` configuration option
- Removed `afterUnsubscribeSync` hook
- Removed sync job infrastructure
### Security
- Added webhook signature verification with timestamp validation
- Webhook secrets stored securely in Newsletter Settings
### Migration Guide
If you were using unsubscribe sync:
1. Remove any `unsubscribeSync` configuration from your plugin setup
2. Configure webhooks in your Broadcast dashboard (see README)
3. Add the webhook secret to your Newsletter Settings
## [0.20.7] - 2025-08-02
### Added
- **Comprehensive Email Wrapper System** - Unified email rendering that uses the same wrapper for previews and actual sends
- Preview component now passes ALL form fields to the preview endpoint as `documentData`
- Custom wrappers receive complete document data, not just content
- Consistent HTML output between preview and actual email sends
- Support for accessing any custom fields added to broadcasts collection
- Wrapper is applied during actual send operations, not just previews
### Enhanced
- **Email Preview Component** - Builds document data from all form fields for wrapper access
- Collects all field values using `useFormFields` hook
- Passes complete form state to preview endpoint
- Enables custom wrappers to access metadata like slug, issueNumber, custom fields
- **Preview Endpoint** - Updated to accept and forward documentData to email wrapper
- Receives documentData from preview component
- Passes through to convertToEmailSafeHtml function
- Maintains backward compatibility with existing implementations
- **Email Wrapper Interface** - Enhanced type definitions for better developer experience
- Added `EmailWrapperOptions` interface with documentData support
- Updated `CustomEmailWrapper` type for consistency
- Generic `Record<string, any>` allows any custom fields
- **Broadcast Sync Hooks** - Now apply wrapper during actual email sends
- Create operation uses wrapper when syncing to provider
- Update operation maintains wrapper consistency
- Deferred creates (from draft to published) include wrapper
- Same HTML template used for both preview and actual sends
### Technical Changes
- Updated `convertToEmailSafeHtml` to accept documentData in options
- Modified all sync operations in Broadcasts collection to use email preview config
- Wrapper customization now available throughout the email lifecycle
- No breaking changes - wrapper remains optional with sensible defaults
### Benefits
- **Flexibility** - Users can pass any custom fields without plugin modifications
- **Consistency** - Identical HTML in preview and actual email sends
- **Future Proof** - Add new fields to broadcasts without updating plugin code
- **No Breaking Changes** - Existing implementations continue to work unchanged
## [0.20.6] - 2025-08-01
### Fixed
- **Preview Content Path** - Fixed preview component to correctly access nested content fields
- Changed from trying multiple access patterns to using the correct flattened field name
- Content is now accessed via `fields?.['contentSection.content']` using dot notation
- Removed debug logging and simplified content access logic
- Preview now properly finds content in the nested `contentSection.content` field structure
### Technical Changes
- Updated field access pattern to match Payload's flattened field naming convention
- Simplified content value retrieval by using the correct dot notation path
- Removed unnecessary fallback patterns that were trying incorrect field paths
## [0.20.5] - 2025-08-01
### Fixed
- **Manual Preview Button** - Replaced automatic preview with manual "Generate Preview" button
- Fixed content access issue where preview couldn't find content due to field group separation
- Changed from `data.content` to `fields?.contentSection?.content` using `useFormFields` hook
- Removed automatic hot-reloading in favor of user-controlled preview generation
- Added "Hide Preview" and "Refresh Preview" buttons for better control
- Preview now correctly accesses content from nested field groups
### Enhanced
- **Better Error Handling** - Clear error messages when no content is available
- **Improved UX** - Manual preview button prevents excessive API calls during content editing
- **Proper Form Data Access** - Uses Payload's `useFormFields` hook to access all form fields across groups
### Technical Changes
- Component now implements `UIFieldClientComponent` interface from Payload
- Removed automatic `useEffect` triggers and debouncing
- Fixed field path from `data.content` to `fields?.contentSection?.content`
- Maintains 600px iframe height for consistent preview display
## [0.20.4] - 2025-07-31
### Added
- **Email Preview Functionality Restored** - Full email preview functionality in admin interface
- Interactive preview component with live content updates
- Real-time iframe rendering of email HTML using the preview endpoint
- Debounced API calls to prevent excessive requests during content editing
- Auto-resizing iframe that adjusts to email content height
- Comprehensive error handling with user-friendly error messages
- Loading states and empty content placeholders for better UX
- Subject line display in preview header
- Preview updates automatically when content, subject, or preheader changes
### Enhanced
- **BroadcastInlinePreview Component**
- Replaced placeholder component with fully functional preview
- Added React hooks for state management (useState, useEffect, useRef)
- Integrated with existing `/api/broadcasts/preview` endpoint
- Added proper TypeScript types and interfaces
- Includes responsive iframe with cross-origin safety measures
- 500ms debounce to optimize API calls during content editing
### Fixed
- **Preview Endpoint Response Format** - Updated to include both `html` and `preview.html` fields for compatibility
- **ESLint Compliance** - Resolved all linting errors in admin components
- **Admin Bundle Integrity** - Maintained separation of server dependencies while restoring functionality
### Technical Changes
- Updated admin component exports to use direct type imports from components
- Removed redundant admin/types.ts file in favor of component-level type exports
- Enhanced preview endpoint to return HTML in multiple response formats
- Added proper error boundaries and loading states in preview component
- Maintained all architectural improvements from v0.20.3 bundle separation
### Validation
- ✅ Preview component fetches and displays email HTML correctly
- ✅ Preview updates in real-time as content changes
- ✅ Error states handled gracefully with retry capability
- ✅ Loading states provide good user experience
- ✅ Admin bundle contains no server dependencies
- ✅ All linting errors resolved
- ✅ Build and bundle validation passes
- ✅ TypeScript types are properly exported and available
## [0.20.3] - 2025-07-31
### Fixed
- **CRITICAL: Admin Bundle Server Dependencies** - Eliminated all Node.js server dependencies from admin bundle
- Reorganized source code into strict server/, client/, admin/, shared/ separation
- Created pure React admin components that don't depend on Node.js built-ins
- Updated build system with strict external dependencies for admin bundle
- Added bundle validation script to prevent server dependencies in browser bundles
- Fixed Next.js App Router compatibility issues with worker_threads, node:assert, and pino dependencies
### Breaking Changes (None)
- Import paths remain unchanged - full backward compatibility maintained
- All existing functionality preserved with improved bundle separation
### Technical Changes
- Reorganized source structure: server/, client/, admin/, shared/ directories
- Created browser-only admin components without server dependencies
- Updated tsup config to strictly external Node.js modules in admin bundle
- Added automated bundle validation in build process
- Reduced admin bundle size by eliminating server code
### Validation
- ✅ Admin bundle contains no worker_threads, node:assert, pino dependencies
- ✅ Client bundle contains no server-side modules
- ✅ Server bundle maintains full server functionality
- ✅ All existing APIs and components work unchanged
## [0.20.2] - 2025-07-31
### Fixed
- **CRITICAL: Next.js App Router createContext Error** - Complete architectural fix for Next.js App Router compatibility
- Separated server and client entry points to prevent React context issues during server-side initialization
- Created dedicated `server.ts`, `client.ts`, and `admin.ts` entry points
- Fixed server-side React context imports that caused `createContext is not a function` errors
- Updated package.json exports to properly route to server-safe and client-safe bundles
- Implemented server-safe plugin configuration storage using simple object store
- Updated build system to generate separate bundles with proper "use client" directives
### Breaking Changes (Minor)
- **Import Path Changes**:
- Admin components: `import { BroadcastInlinePreview } from 'payload-plugin-newsletter/admin'` (was `/components`)
- Client components: `import { NewsletterForm } from 'payload-plugin-newsletter/client'`
- Server exports: `import { newsletterPlugin } from 'payload-plugin-newsletter'` (unchanged)
- **Context API Changes**:
- Server-side config access through `getPluginConfig()` instead of React context
- Client-side React context requires explicit `PluginConfigProvider` setup
### Technical Changes
- Added separate entry points: `src/server.ts`, `src/client.ts`, `src/admin.ts`
- Created `ServerContext.ts` for server-safe configuration storage
- Created `ClientContext.tsx` for client-side React context
- Updated tsup config to build multiple entry points with proper directives
- Fixed plugin initialization to use server-safe config storage
- Updated package.json exports to route to appropriate bundles
## [0.20.1] - 2025-07-31
### Fixed
- **Next.js App Router Compatibility** - Fixed React `createContext` error in Next.js App Router
- Added missing `"use client"` directive to `PluginConfigContext`
- Added `"use client"` directive to component barrel exports
- Fixed server-side rendering issues with client components
- Improved compatibility with Next.js 15+ App Router
### Technical Changes
- Added `"use client"` directive to `PluginConfigContext.tsx`
- Added `"use client"` directive to `EmptyField.tsx`
- Added `"use client"` directive to component index files
- Ensured proper server/client component separation
## [0.20.0] - 2025-07-31
### Added
- **Email Preview Customization** - Full control over email preview rendering
- New `emailPreview` customization options in `BroadcastCustomizations` interface
- `wrapInTemplate` option to disable default email template wrapping
- `customWrapper` function for custom email template wrappers
- Support for both sync and async custom wrapper functions
- Pass subject and preheader to custom wrapper for complete control
- `customPreviewComponent` option (planned) for replacing the entire preview component
### Enhanced
- **Plugin Configuration Context**
- Added `PluginConfigContext` for passing configuration throughout component tree
- `usePluginConfig` hook for required config access
- `usePluginConfigOptional` hook for safe optional config access
- Context provider integration in component hierarchy
- **Email Preview Component**
- Updated to respect email preview customization options
- Backward compatible with default template wrapping behavior
- Support for both prop-based and context-based config passing
- Seamless integration with custom wrapper functions
- **Preview Endpoint**
- Updated to use email preview customization options
- Consistent behavior between UI preview and API preview
- Maintains all existing functionality while adding customization
### Technical Improvements
- **Type Safety** - Full TypeScript support for all customization options
- **Backward Compatibility** - All changes maintain 100% backward compatibility
- **Flexible Architecture** - Easy to extend with additional customization options
- **Performance** - No performance impact when customization is not used
### Developer Experience
- **Easy Configuration** - Simple to disable template wrapping or provide custom wrapper
- **Context Support** - Components can access config without prop drilling
- **Comprehensive Types** - Well-documented interfaces with examples
## [0.19.0] - 2025-07-30
### Added
- **Responsive Email Design** - Complete overhaul of email template for mobile-first responsive design
- Mobile-optimized email template with responsive CSS media queries
- Responsive typography with proper mobile font sizes and line heights
- Mobile-friendly image scaling and spacing
- Dark mode support with `prefers-color-scheme` media queries
- Comprehensive email client compatibility (Outlook, Gmail, Apple Mail)
- Mobile-specific CSS classes for precise responsive control
### Enhanced
- **Email Template Architecture**
- Completely redesigned `wrapInEmailTemplate` function with responsive structure
- Added proper viewport meta tags and email client compatibility headers
- Enhanced preheader text formatting with proper hiding techniques
- Improved table-based layout structure for email client consistency
- Better font rendering with `-webkit-font-smoothing` and `-moz-osx-font-smoothing`
- **Typography System**
- Responsive heading sizes that scale appropriately on mobile devices
- H1: 32px desktop → 24px mobile with optimized line-height
- H2: 24px desktop → 20px mobile with optimized line-height
- H3: 20px desktop → 16px mobile with optimized line-height
- Enhanced paragraph styling with consistent font-size and line-height
- Improved list styling with proper spacing and typography
- **Image Handling**
- Responsive images with `mobile-width-100` class for full-width scaling
- Enhanced image captions with mobile-optimized typography
- Proper image border-radius for modern email design
- Better image centering and spacing on all screen sizes
### Technical Improvements
- **CSS Media Queries** - Comprehensive mobile-first responsive design
- `@media only screen and (max-width: 640px)` breakpoint
- Mobile utility classes: `.mobile-hide`, `.mobile-center`, `.mobile-width-100`
- Mobile padding classes: `.mobile-padding`, `.mobile-padding-sm`
- Mobile typography classes: `.mobile-font-size-14/16/20/24`
- Mobile spacing classes: `.mobile-margin-bottom-16/20`
- **Email Client Compatibility**
- Outlook-specific MSO conditional comments and fixes
- Apple Mail message reformatting prevention
- Gmail and other client table-based layout optimization
- Cross-client font fallback stack
- **Dark Mode Support**
- CSS custom properties for dark mode backgrounds and text
- Proper border color adjustments for dark themes
- Future-ready design system for theme customization
### Breaking Changes
- None - all changes maintain backward compatibility with existing email content
### Browser/Client Support
- ✅ Outlook 2016+ (Windows/Mac)
- ✅ Gmail (Web/Mobile/App)
- ✅ Apple Mail (macOS/iOS)
- ✅ Yahoo Mail
- ✅ Thunderbird
- ✅ Mobile email clients (iOS/Android)
## [0.18.0] - 2025-07-30
### Added
- **Media Field Population in Custom Blocks** - Fixed critical issue where media fields in custom blocks weren't populated during email conversion
- Added automatic media field population in preview endpoint before email conversion
- Media fields now receive full media objects with URLs instead of just ID strings
- Added `populateFields` option to `BroadcastCustomizations` interface for configurable field population
- Added recursive population support for array fields containing upload fields
- Comprehensive logging for media population success and failures
- Both email previews and sent emails now properly populate media relationships
### Enhanced
- **Preview Endpoint** - Significantly improved custom block support
- Preview endpoint now populates media fields before calling custom block converters
- Custom blocks with images now display correctly in email previews
- Added detailed logging for debugging media population issues
- **Broadcast Sync Logic** - Applied media population to all broadcast operations
- Create operation now populates media fields before provider sync
- Update operation populates media fields when content changes
- Deferred create operation (empty → content) now handles media population
- Ensures consistency between previews and actual sent emails
### Technical
- **New Helper Functions**
- `populateMediaFields()` - Recursively finds and populates upload fields in Lexical content
- `populateBlockMediaFields()` - Handles individual block media field population
- Support for both direct upload fields and upload fields within arrays
- Automatic detection of upload fields based on custom block configuration
- MongoDB ObjectId pattern matching for field population decisions
### Types
- **Enhanced BroadcastCustomizations Interface**
- Added `populateFields` option with string array or function signature
- Comprehensive documentation with usage examples
- Support for block-type-specific field population logic
### Breaking Changes
- None - all changes are backward compatible and additive
## [0.17.4] - 2025-07-30
### Fixed
- **Resolved Lint Errors** - Fixed CI/CD build failures caused by lint errors
- Removed unused imports from `endpoints/broadcasts/index.ts`
- Prefixed unused `collectionSlug` parameter with underscore in `preview.ts`
- Ensures clean build and successful npm publish
## [0.17.3] - 2025-07-30
### Fixed
- **Duplicate Collection Slug in Endpoint Paths** - Fixed broadcast endpoints having duplicate collection slugs
- Removed collection slug from endpoint paths as Payload automatically prepends it
- Changed `/${collectionSlug}/preview` to `/preview`
- Changed `/${collectionSlug}/:id/send` to `/:id/send`
- Changed `/${collectionSlug}/:id/schedule` to `/:id/schedule`
- Changed `/${collectionSlug}/:id/test` to `/:id/test`
- Fixes 404 errors when accessing endpoints from `/api/broadcasts/preview` instead of `/api/broadcasts/broadcasts/preview`
- Client code can now properly access endpoints at their expected paths
## [0.17.2] - 2025-07-29
### Fixed
- **Broadcast Endpoints Registration** - Fixed endpoints not being accessible in Payload v3
- Moved broadcast endpoints from global endpoints to collection endpoints
- Endpoints are now properly registered on the broadcasts collection
- Fixes 404 errors for all broadcast endpoints (/preview, /test, /send, /schedule)
- Aligns with Payload v3 architecture where collection endpoints should be defined on the collection
### Changed
- `createBroadcastManagementEndpoints` now returns empty array (kept for backward compatibility)
- Broadcast endpoints are defined directly in the broadcasts collection configuration
## [0.17.1] - 2025-07-29
### Fixed
- **Email Preview Endpoint Path** - Fixed incorrect path for broadcast preview endpoint
- Removed extra `/api` prefix from preview endpoint path
- Preview endpoint now correctly registers at `/{collectionSlug}/preview`
- Fixes 404 error when accessing email preview from the admin UI
## [0.17.0] - 2025-07-29
### Added
- **Custom Block Email Converter Support** - Added support for custom block email conversion in broadcasts
- New `customBlockConverter` option in `BroadcastCustomizations` interface
- Allows users to provide their own email conversion logic for custom Lexical blocks
- Converter receives block node and media URL, returns email-safe HTML
- Supports async operations for fetching external data during conversion
- **Server-Side Email Preview Generation** - Implemented server-side email preview for accurate rendering
- New `/api/broadcasts/preview` endpoint for generating email previews
- Updated BroadcastInlinePreview component to use server-side preview
- Ensures preview exactly matches what will be sent via email
- Custom block converters work in both preview and sent emails
### Changed
- **Email Conversion Functions Now Async** - All email conversion functions are now async to support custom converters
- `convertToEmailSafeHtml` and all internal converters are now async
- Maintains backward compatibility - existing code continues to work
- Enables custom converters to perform async operations like API calls
### Technical
- Updated `convertNode`, `convertParagraph`, `convertHeading`, etc. to be async functions
- Added `customBlockConverter` parameter throughout the email conversion pipeline
- Custom converter is called first, falls back to default handling if it returns empty
- Error handling for custom converter failures with graceful fallback
- Preview endpoint uses same conversion logic as email sending for consistency
## [0.16.10] - 2025-01-29
### Fixed
- **Corrected Syntax Errors** - Fixed TypeScript compilation errors in broadcast afterChange hook
- Simplified deferred create logic to avoid nested try-catch blocks
- Removed duplicate error handling and extra braces
- Fixed all TypeScript compilation errors
- Maintained functionality for deferred provider sync
### Technical
- Cleaned up afterChange hook structure
- Simplified error handling flow
- Removed redundant code blocks
- All TypeScript errors resolved
## [0.16.9] - 2025-01-29
### Fixed
- **Deferred Provider Sync for Empty Broadcasts** - Fixed issue where broadcasts created empty were never synced to provider
- Update operation now handles "deferred create" scenario when providerId is missing
- When a broadcast has subject and content but no providerId, it creates the broadcast in the provider
- Normal update sync works for broadcasts that already exist in the provider
- Resolves workflow: create empty → add content → save → now syncs to provider
### Technical
- Modified update operation handler to check for missing providerId
- Added deferred create logic in update afterChange hook
- Separated normal update logic to only run when providerId exists
- Added comprehensive error handling for both deferred create and normal update scenarios
## [0.16.8] - 2025-01-29
### Fixed
- **Handle Empty Content When Creating Broadcasts** - Fixed error when creating broadcasts without content
- Added null/undefined check in convertToEmailSafeHtml function
- Skip provider sync when subject or content is missing on create
- Skip provider sync when content is empty after conversion
- Prevents "Cannot destructure property 'root' of 'editorState'" error
- Broadcasts can now be created empty and synced later when content is added
### Technical
- Updated convertToEmailSafeHtml to accept undefined/null editorState
- Added pre-sync validation in afterChange hook for create operations
- Empty broadcasts are saved in Payload but not synced to provider until content is added
## [0.16.7] - 2025-07-29
### Added
- **Comprehensive Diagnostic Logging** - Added extensive logging to diagnose broadcast sync issues
- Logs the HTML content conversion process
- Shows exactly what data is being sent to the Broadcast API (with preview)
- Displays request URL, method, and body structure
- Shows API response status and headers
- Captures and logs all error types (Error objects, strings, JSON responses)
- Logs raw errors to identify unexpected error formats
### Improved
- **Better Error Visibility** - Enhanced error handling to capture more details
- Raw error logging to see the actual error structure
- Multiple error format handlers (Error, string, object, unknown)
- Response body parsing for API errors
- Document context logging when errors occur
- API request/response details in provider logs
### Technical
- Added pre-API call logging in afterChange hook
- Added comprehensive error logging in BroadcastApiProvider
- Logs help identify if issues are with content, API format, or authentication
## [0.16.6] - 2025-07-29
### Fixed
- **Critical: Update Sync Now Works** - Fixed the afterChange hook that was blocking update operations
- Removed the `operation !== 'create'` check that prevented the afterChange hook from running on updates
- Moved update sync logic from beforeChange to afterChange for proper architectural pattern
- Updates are now synced AFTER they're saved to Payload, ensuring consistency
- Provider sync failures no longer block Payload updates
### Improved
- **Better Hook Architecture** - Sync operations now happen in the correct lifecycle stage
- beforeChange was architecturally wrong - if provider sync failed, data would be inconsistent
- afterChange ensures Payload data is saved first, then syncs to provider
- More resilient to network failures and API errors
### Technical
- Consolidated create and update logic in a single afterChange hook
- Added comprehensive content change detection before syncing
- Enhanced logging for update sync operations
- Removed redundant beforeChange hook logic
## [0.16.5] - 2025-07-29
### Breaking Changes
- **Field Renaming** - Renamed `status` field to `sendStatus` throughout the codebase
- This avoids confusion with Payload's built-in `_status` field (draft/published)
- Database field is now `sendStatus` for email send status (draft, scheduled, sending, sent, etc.)
- All references in providers, endpoints, and types have been updated
- If you have existing broadcast data with a `status` field, you'll need to migrate it to `sendStatus`
### Fixed
- **Update Sync** - Fixed issue where broadcast updates made in Payload weren't syncing to the Broadcast provider
- The update hook now correctly checks `sendStatus` instead of the non-existent `status` field
- Provider can now properly determine if a broadcast is editable based on its send status
### Technical
- Updated `Broadcast` type interface to use `sendStatus` property
- Updated all provider implementations (Broadcast and Resend) to use `sendStatus`
- Updated send and schedule endpoints to set `sendStatus` field
- All TypeScript errors resolved
## [0.16.4] - 2025-07-27
### Added
- **Access Control for Broadcasts** - Added proper access control to the Broadcasts collection
- Public read access for all users
- Create, update, and delete operations require authenticated users
- Prevents unauthorized modifications to broadcast content
- Follows Payload's standard access control patterns
### Improved
- **Enhanced Update Sync Debugging** - Added detailed logging for broadcast update synchronization
- Logs when update hooks are triggered with operation details
- Shows what fields are being synced to the provider
- Helps diagnose why updates might not be syncing
- Added info logging for skipped updates due to status restrictions
- **Clearer Field Naming** - Renamed `status` field to `sendStatus` to avoid confusion with Payload's `_status`
- Database field is now `sendStatus` (draft, scheduled, sending, sent, etc.)
- Payload's versioning field remains `_status` (draft, published)
- Added virtual `status` field for API backward compatibility
- Makes it clear which status controls email sending vs content publishing
## [0.16.3] - 2025-07-27
### Improved
- **Enhanced Error Logging** - Improved error logging for broadcast operations
- Now logs full error details including message, stack trace, and any additional error properties
- Helps diagnose API connection issues, authentication failures, and validation errors
- Structured error logging makes it easier to identify root causes
- Applied to all broadcast hooks: create, update, delete, and send
## [0.16.2] - 2025-07-27
### Fixed
- **Configuration Consistency** - Fixed broadcast operations to read from Newsletter Settings collection
- Broadcast create/update/delete operations now check Newsletter Settings first before falling back to env vars
- This matches the behavior of email operations (magic links, welcome emails)
- Resolves issue where broadcasts failed when env vars were missing despite settings being configured
- Added `getBroadcastConfig` utility for consistent configuration retrieval
### Added
- **Configuration Utilities** - New utilities for consistent provider configuration
- `getBroadcastConfig` - Gets Broadcast provider config from settings or env vars
- `getResendConfig` - Gets Resend provider config from settings or env vars
- Both utilities handle errors gracefully with fallback to env vars
## [0.16.1] - 2025-07-27
### Fixed
- **Critical Bug Fix** - Fixed afterChange hook placement for sending broadcasts
- The send hook was incorrectly placed in the `afterDelete` array instead of `afterChange`
- This prevented broadcasts from being sent when published
- Publishing broadcasts now correctly triggers the send functionality
## [0.16.0] - 2025-07-27
### Changed
- **Send = Publish Workflow** - Simplified broadcast sending to use Payload's native draft/publish system
- Publishing a broadcast now automatically sends it via the configured email provider
- Removed custom Send/Schedule modal in favor of Payload's built-in UI
- Scheduled publishing supported via Payload's Jobs Queue system
- Breaking: Removed `SendBroadcastModal` and `ActionsCell` components
- **Streamlined UI** - Removed custom action buttons from broadcasts list view
- Users now use standard Payload publish/schedule functionality
- Cleaner interface that follows Payload's patterns
- Less code to maintain while providing better integration
### Added
- **Automatic Send on Publish** - New `afterChange` hook that sends broadcasts when published
- Checks if broadcast is transitioning to published status
- Automatically calls provider's send method
- Updates broadcast status to "sending" after successful send
- Handles failures gracefully with status update to "failed"
- **Jobs Queue Documentation** - Added comprehensive setup instructions for scheduled publishing
- Vercel Cron configuration example
- Security setup with CRON_SECRET
- Step-by-step guide for enabling scheduled broadcasts
### Removed
- **Custom UI Components** (Breaking Change)
- `SendBroadcastModal` - Custom send/schedule modal
- `ActionsCell` - Custom action buttons in list view
- `actions` field from Broadcasts collection
- These are replaced by Payload's native publish/schedule functionality
### Technical
- Enabled `versions` configuration on Broadcasts collection with drafts and scheduled publishing
- Updated default columns to show both `_status` (Draft/Published) and `status` (send status)
- Improved TypeScript exports by removing deleted component references
- All tests passing with minor version upgrade
### Migration Guide
If you were using the custom Send/Schedule modal:
1. The functionality is now built into Payload's publish system
2. To send immediately: Click "Publish"
3. To schedule: Click "Schedule" (requires Jobs Queue setup)
4. Remove any imports of `SendBroadcastModal` or `ActionsCell` from your code
## [0.15.1] - 2025-07-27
### Fixed
- **Email-Compatible Block Editor** - Resolved Next.js serialization errors with custom blocks
- Custom blocks are now processed server-side using Lexical's proven BlocksFeature pattern
- Prevents "Functions cannot be passed directly to Client Components" errors
- Maintains full email compatibility while enabling custom block functionality
- **Block Validation System** - Added validation utilities for email compatibility
- `validateEmailBlocks()` warns about potentially incompatible block types
- `createEmailSafeBlocks()` processes blocks for email-safe configurations
- Automatic detection of complex field types that may not render in email clients
### Improved
- **Server-Side Block Processing** - Enhanced `createEmailLexicalEditor()` function
- Processes custom blocks into Lexical editor configuration before client serialization
- Clean separation between email-compatible and web-only content blocks
- Better performance through pre-configured editor instances
- **Enhanced Documentation** - Updated extension points guide with new approach
- Examples showing both legacy and new server-side processing methods
- Block validation utilities documentation
- Email compatibility best practices
### Technical
- Added `createEmailLexicalEditor()` for server-side editor configuration
- Enhanced `createEmailContentField()` to accept pre-configured editors
- New utility exports: `validateEmailBlocks`, `createEmailSafeBlocks`
- Improved TypeScript support for custom block configurations
## [0.15.0] - 2025-07-27
### Added
- **Plugin Extensibility System** - New customization API for extending the Broadcasts collection
- `additionalFields` - Add custom fields to the Broadcasts collection
- `customBlocks` - Extend the email content editor with custom blocks
- `fieldOverrides` - Override default field configurations (e.g., content field customization)
- Full TypeScript support for all customization options
- **New Export Paths** for advanced usage
- `payload-plugin-newsletter/fields` - Access field factories and configurations
- `payload-plugin-newsletter/collections` - Access collection factories
- Export `createEmailSafeFeatures` function for custom rich text configurations
- **Comprehensive Documentation** - New extension points guide with examples and best practices
- Email-safe block creation guidelines
- TypeScript support documentation
- Migration and backward compatibility information
### Improved
- Enhanced `createEmailContentField` to accept `additionalBlocks` parameter
- Maintained full backward compatibility with existing installations
- Added examples for e-commerce, SaaS, and content marketing use cases
### Technical
- Updated build configuration to include new export paths
- Added proper TypeScript interfaces for customization options
- Enhanced field and collection factories for better extensibility
## [0.14.3] - 2025-07-23
### Fixed
- Sign-in emails now use the magic link subject line from Newsletter Settings
- Broadcast provider now properly sends the from name along with the email address
## [0.14.2] - 2025-07-22
### Added
- Custom email template support for transactional emails (magic link, welcome, sign-in)
- Configure via `customTemplates` in plugin config
- Full React Email component support
- Fallback to built-in templates when custom ones not provided
- Comprehensive email template documentation
- Guide for creating custom broadcast templates
- Guide for creating custom transactional templates
- Examples and best practices for template development
- Extension patterns for advanced use cases
### Fixed
- Custom templates now properly used when configured in plugin settings
- All email rendering functions now accept config parameter for template customization
## [0.14.1] - 2025-07-22
### Changed
- Improved email preview in Broadcasts collection to use full container height
- Email preview now utilizes all available vertical space
- Maintains realistic email widths (600px for desktop, 375px for mobile)
- Added scrolling within preview container for longer email content
- Better space utilization for viewing and editing broadcast emails
## [0.14.0] - 2025-07-22
### Added
- New authentication configuration options for flexible subscriber management
- `auth.allowUnsubscribedSignin`: Allow unsubscribed users to sign in
- `auth.allowResubscribe`: Allow unsubscribed users to resubscribe
- Improved subscribe endpoint behavior:
- Already subscribed users now receive a sign-in link instead of an error
- Unsubscribed users can resubscribe (when enabled)
- Enhanced response formats with status indicators:
- `requiresSubscribe`: Indicates user needs to subscribe first
- `requiresResubscribe`: Indicates user needs to resubscribe
- `wasResubscribed`: Indicates user was successfully resubscribed
- `alreadySubscribed`: Indicates user is already subscribed
### Changed
- Sign-in endpoint now returns more detailed error information for better UX
- Subscribe endpoint handles existing subscribers more gracefully
### Fixed
- Unsubscribed users can now manage their preferences when `allowUnsubscribedSignin` is enabled
## [0.13.3] - 2025-07-21
### Added
- Support for custom redirect URLs after successful subscriber sign-in
- Added `redirectUrl` parameter to signin endpoint
- Magic link URLs now include the redirect parameter to maintain context after authentication
- Enables seamless user experience when accessing protected content
### Fixed
- Magic link generation now properly includes redirect URL parameter
## [0.13.2] - 2025-07-21
### Fixed
- Fixed `useAsTitle` configuration error in Broadcasts collection
- Moved `subject` field to top level as Payload v3 doesn't support nested field references in `useAsTitle`
- Updated all component references from `contentSection.subject` to `subject`
- Maintained split-screen layout with subject field appearing above the content sections
### Breaking Changes
- The `subject` field location has changed in the data structure:
- Old: `broadcast.contentSection.subject`
- New: `broadcast.subject`
- If you have existing broadcasts, you may need to migrate the subject field data
## [0.13.1] - 2025-07-21
### Fixed
- Fixed Broadcast API subscriber update method to match API documentation
- Added comprehensive debug logging for email service initialization and subscriber sync
- Improved error handling in subscriber hooks to surface sync issues
### Added
- Debug logging for troubleshooting subscriber sync with email providers
- Better error messages when email service configuration fails
## [0.13.0] - 2025-07-21
### Changed
- **BREAKING**: Broadcasts collection field structure has been updated for improved layout
- Fields `subject`, `preheader`, and `content` are now nested under `contentSection` group
- Email preview is now displayed side-by-side with content fields on desktop screens
- Responsive design switches to vertical layout on screens smaller than 1024px
### Migration Guide
If you have existing broadcast data, you'll need to migrate the field structure:
- `subject` → `contentSection.subject`
- `preheader` → `contentSection.preheader`
- `content` → `contentSection.content`
## [0.12.3] - 2025-07-20
### Fixed
- Fixed import map component path references to use package exports instead of file paths
- Resolved "PayloadComponent not found in importMap" errors in Payload v3 projects
- Added missing component exports (StatusBadge, ActionsCell, EmptyField)
## [0.12.2] - 2025-07-20
### Documentation
- Updated all documentation to reflect single-channel architecture
- Removed outdated references to 'name' field in broadcasts
- Added comprehensive broadcast sync documentation
- Updated email preview and React Email template documentation
- Revised multi-channel setup guide to indicate it's no longer supported
- Enhanced README with broadcast management and custom template examples
## [0.12.1] - 2025-07-20
### Fixed
- Resolved ESLint errors in email preview components
- Removed unused imports and variables
- Fixed console.info statements in template loader
## [0.12.0] - 2025-07-20
### Added
- Email preview feature for broadcasts with inline preview component
- React Email integration for reliable email template rendering
- Custom email template support
- Desktop and mobile preview modes
### Changed
- Broadcast collection now includes inline email preview below content editor
## [0.11.0] - 2025-07-20
### Added
- Enhanced rich text editor for broadcast emails with:
- Fixed toolbar showing available formatting options
- Inline toolbar for text selection
- Image upload support with Media collection integration
- Custom email blocks (Button and Divider)
- Enhanced link feature with "open in new tab" option
- Email preview feature for broadcasts:
- Live preview with manual update button
- Desktop and mobile responsive views
- React Email template rendering
- Custom template support via `email-templates/broadcast-template.tsx`
- Inline preview below content editor
- Comprehensive image handling in email HTML conversion:
- Responsive images with proper email-safe HTML
- Support for captions and alt text
- Automatic media URL handling for different storage backends
- New utilities and components:
- `contentTransformer` for preview content processing
- `templateLoader` for custom template discovery
- `DefaultBroadcastTemplate` bundled email template
- `BroadcastInlinePreview` component
- Documentation:
- Media collection setup guide (`docs/guides/media-collection-setup.md`)
- Email preview feature guide (`docs/features/email-preview.md`)
- Prerequisites section in README mentioning Media collection requirement
### Changed
- Removed 'name' field from Broadcasts collection (now uses 'subject' as title)
- Updated Broadcast collection admin UI:
- Uses subject as the display title
- Shows recipientCount in default columns instead of name
- Enhanced `convertToEmailSafeHtml` utility to handle:
- Upload nodes for images
- Custom block nodes (button and divider)
- Media URL configuration
- Improved link handling with target attribute support
- Broadcast API sync now uses subject as the name field
### Fixed
- Broadcast hooks now properly handle the absence of name field
- Email preview components updated to work without channel references
## [0.10.0] - 2025-07-20
### Changed
- **BREAKING**: Simplified plugin architecture to single-channel design
- Removed Channels collection entirely
- Each Payload instance now connects to a single Broadcast channel
- Channel is determined by the API token (Broadcast tokens are channel-specific)
- Removed `channelId` field from Broadcast type
- Removed channel management methods from providers
- Updated newsletter management configuration
- Removed `collections.channels` from plugin config
- Broadcasts no longer have channel relationships
- All broadcasts use the global provider configuration
- Improved provider capabilities
- Set `supportsMultipleChannels` to `false`