payload-plugin-newsletter
Version:
Complete newsletter management plugin for Payload CMS with subscriber management, magic link authentication, and email service integration
351 lines (348 loc) • 9.42 kB
text/typescript
import { Field } from 'payload';
interface NewsletterPluginConfig {
/**
* Enable or disable the plugin
* @default true
*/
enabled?: boolean;
/**
* Slug for the subscribers collection
* @default 'subscribers'
*/
subscribersSlug?: string;
/**
* Slug for the newsletter settings global
* @default 'newsletter-settings'
*/
settingsSlug?: string;
/**
* Authentication configuration for magic links
*/
auth?: {
/**
* Enable magic link authentication
* @default true
*/
enabled?: boolean;
/**
* Token expiration time
* @default '7d'
*/
tokenExpiration?: string;
/**
* Path where magic link redirects
* @default '/newsletter/verify'
*/
magicLinkPath?: string;
};
/**
* Access control configuration
*/
access?: {
/**
* Custom function to determine if a user is an admin
* @param user - The authenticated user object
* @returns true if the user should have admin access
*/
isAdmin?: (user: any) => boolean;
};
/**
* Email provider configuration
*/
providers: {
/**
* Default provider to use
*/
default: 'resend' | 'broadcast' | string;
/**
* Resend provider configuration
*/
resend?: ResendProviderConfig;
/**
* Broadcast provider configuration
*/
broadcast?: BroadcastProviderConfig;
};
/**
* Field customization options
*/
fields?: {
/**
* Override default fields
*/
overrides?: (args: {
defaultFields: Field[];
}) => Field[];
/**
* Additional custom fields
*/
additional?: Field[];
};
/**
* Email template components
*/
templates?: {
/**
* Welcome email template
*/
welcome?: React.ComponentType<WelcomeEmailProps>;
/**
* Magic link email template
*/
magicLink?: React.ComponentType<MagicLinkEmailProps>;
};
/**
* Plugin hooks
*/
hooks?: {
beforeSubscribe?: (args: BeforeSubscribeArgs) => void | Promise<void>;
afterSubscribe?: (args: AfterSubscribeArgs) => void | Promise<void>;
beforeUnsubscribe?: (args: BeforeUnsubscribeArgs) => void | Promise<void>;
afterUnsubscribe?: (args: AfterUnsubscribeArgs) => void | Promise<void>;
};
/**
* UI component overrides
*/
components?: {
signupForm?: React.ComponentType<SignupFormProps>;
preferencesForm?: React.ComponentType<PreferencesFormProps>;
};
/**
* Feature flags
*/
features?: {
/**
* Lead magnet configuration
*/
leadMagnets?: {
enabled?: boolean;
collection?: string;
};
/**
* Post-signup survey configuration
*/
surveys?: {
enabled?: boolean;
questions?: SurveyQuestion[];
};
/**
* UTM tracking configuration
*/
utmTracking?: {
enabled?: boolean;
fields?: string[];
};
/**
* Newsletter scheduling configuration
*/
newsletterScheduling?: {
enabled?: boolean;
/**
* Collections to add newsletter fields to
* Can be a string for single collection or array for multiple
* @example 'articles' or ['articles', 'posts', 'updates']
*/
collections?: string | string[];
/**
* Field configuration
*/
fields?: {
/**
* Group name for newsletter fields
* @default 'newsletterScheduling'
*/
groupName?: string;
/**
* Rich text field name to use for content
* @default 'content'
*/
contentField?: string;
/**
* Whether to create a markdown companion field
* @default true
*/
createMarkdownField?: boolean;
};
};
};
/**
* Internationalization configuration
*/
i18n?: {
defaultLocale?: string;
locales?: string[];
};
}
interface ResendProviderConfig {
apiKey: string;
fromAddress?: string;
fromName?: string;
audienceIds?: {
[locale: string]: {
production?: string;
development?: string;
};
};
}
interface BroadcastProviderConfig {
apiUrl: string;
tokens: {
production?: string;
development?: string;
};
fromAddress?: string;
fromName?: string;
}
interface EmailProvider {
send(params: SendEmailParams): Promise<void>;
addContact(contact: Subscriber): Promise<void>;
updateContact(contact: Subscriber): Promise<void>;
removeContact(email: string): Promise<void>;
}
interface SendEmailParams {
to: string | string[];
subject: string;
html?: string;
text?: string;
react?: React.ReactElement;
}
interface Subscriber {
id: string;
email: string;
name?: string;
locale?: string;
subscriptionStatus: 'active' | 'unsubscribed' | 'pending';
emailPreferences?: {
newsletter?: boolean;
announcements?: boolean;
[key: string]: boolean | undefined;
};
source?: string;
utmParameters?: {
source?: string;
medium?: string;
campaign?: string;
content?: string;
term?: string;
};
createdAt: string;
updatedAt: string;
}
interface WelcomeEmailProps {
subscriber: Subscriber;
unsubscribeUrl: string;
preferencesUrl: string;
}
interface MagicLinkEmailProps {
magicLinkUrl: string;
subscriber: Subscriber;
}
interface SignupFormProps {
onSuccess?: (subscriber: Subscriber) => void;
onError?: (error: Error) => void;
showName?: boolean;
showPreferences?: boolean;
leadMagnet?: {
id: string;
title: string;
description?: string;
};
className?: string;
styles?: {
form?: React.CSSProperties;
inputGroup?: React.CSSProperties;
label?: React.CSSProperties;
input?: React.CSSProperties;
button?: React.CSSProperties;
buttonDisabled?: React.CSSProperties;
error?: React.CSSProperties;
success?: React.CSSProperties;
checkbox?: React.CSSProperties;
checkboxInput?: React.CSSProperties;
checkboxLabel?: React.CSSProperties;
};
apiEndpoint?: string;
buttonText?: string;
loadingText?: string;
successMessage?: string;
placeholders?: {
email?: string;
name?: string;
};
labels?: {
email?: string;
name?: string;
newsletter?: string;
announcements?: string;
};
}
interface PreferencesFormProps {
subscriber?: Subscriber;
onSuccess?: (subscriber: Subscriber) => void;
onError?: (error: Error) => void;
className?: string;
styles?: {
container?: React.CSSProperties;
heading?: React.CSSProperties;
form?: React.CSSProperties;
section?: React.CSSProperties;
sectionTitle?: React.CSSProperties;
inputGroup?: React.CSSProperties;
label?: React.CSSProperties;
input?: React.CSSProperties;
select?: React.CSSProperties;
checkbox?: React.CSSProperties;
checkboxInput?: React.CSSProperties;
checkboxLabel?: React.CSSProperties;
buttonGroup?: React.CSSProperties;
button?: React.CSSProperties;
primaryButton?: React.CSSProperties;
secondaryButton?: React.CSSProperties;
dangerButton?: React.CSSProperties;
error?: React.CSSProperties;
success?: React.CSSProperties;
info?: React.CSSProperties;
};
sessionToken?: string;
apiEndpoint?: string;
showUnsubscribe?: boolean;
locales?: string[];
labels?: {
title?: string;
personalInfo?: string;
emailPreferences?: string;
name?: string;
language?: string;
newsletter?: string;
announcements?: string;
saveButton?: string;
unsubscribeButton?: string;
saving?: string;
saved?: string;
unsubscribeConfirm?: string;
};
}
interface BeforeSubscribeArgs {
data: Partial<Subscriber>;
req: any;
}
interface AfterSubscribeArgs {
doc: Subscriber;
req: any;
}
interface BeforeUnsubscribeArgs {
email: string;
req: any;
}
interface AfterUnsubscribeArgs {
doc: Subscriber;
req: any;
}
interface SurveyQuestion {
id: string;
question: string;
type: 'text' | 'select' | 'multiselect' | 'radio';
options?: string[];
required?: boolean;
}
export type { AfterSubscribeArgs, AfterUnsubscribeArgs, BeforeSubscribeArgs, BeforeUnsubscribeArgs, BroadcastProviderConfig, EmailProvider, MagicLinkEmailProps, NewsletterPluginConfig, PreferencesFormProps, ResendProviderConfig, SendEmailParams, SignupFormProps, Subscriber, SurveyQuestion, WelcomeEmailProps };