import { deindent } from "../utils/strings"; export const defaultNewTemplateSource = deindent` import { type } from "arktype" import { Container } from "@react-email/components"; import { Subject, NotificationCategory, Props } from "@stackframe/emails"; export const variablesSchema = type({ count: "number" }); export function EmailTemplate({ user, variables }: Props) { return (
Hi {user.displayName}!

count is {variables.count}
); } EmailTemplate.PreviewVariables = { count: 10 } satisfies typeof variablesSchema.infer `; export const previewTemplateSource = deindent` import { Button, Section, Hr, Text, Heading } from "@react-email/components"; import { Subject, NotificationCategory } from "@stackframe/emails"; export const variablesSchema = v => v; export function EmailTemplate({ user, project }) { return ( <>
Verify your email at {project.displayName} Hi{user.displayName ? (", " + user.displayName) : ''}! Please click on the following button to verify your email.

If you were not expecting this email, you can safely ignore it.
) } `; export const emptyEmailTheme = deindent` import { Html, Tailwind, Body } from '@react-email/components'; export function EmailTheme({ children }: { children: React.ReactNode }) { return ( {children} ); } `; export const LightEmailTheme = `import { Html, Head, Tailwind, Body, Container, Section } from '@react-email/components'; import { ThemeProps, ProjectLogo } from "@stackframe/emails"; export function EmailTheme({ children, unsubscribeLink, projectLogos }: ThemeProps) { return (
{children}
{unsubscribeLink && (
Click here to unsubscribe from these emails
)}
); } EmailTheme.PreviewProps = { unsubscribeLink: "https://example.com", } satisfies Partial `; const DarkEmailTheme = `import { Html, Head, Tailwind, Body, Container, Section } from '@react-email/components'; import { ThemeProps, ProjectLogo } from "@stackframe/emails"; export function EmailTheme({ children, unsubscribeLink, projectLogos }: ThemeProps) { return (
{children}
{unsubscribeLink && (
Click here to unsubscribe from these emails
)}
); } EmailTheme.PreviewProps = { unsubscribeLink: "https://example.com", } satisfies Partial `; const ColorfulEmailTheme = `import { Html, Head, Tailwind, Body, Container, Section } from '@react-email/components'; import { ThemeProps, ProjectLogo } from "@stackframe/emails"; export function EmailTheme({ children, unsubscribeLink, projectLogos }: ThemeProps) { return (
{children}
{unsubscribeLink && (
Click here to unsubscribe from these emails
)}
); } EmailTheme.PreviewProps = { unsubscribeLink: "https://example.com", } satisfies Partial `; export const DEFAULT_EMAIL_THEME_ID = "1df07ae6-abf3-4a40-83a5-a1a2cbe336ac"; export const DEFAULT_EMAIL_THEMES = { [DEFAULT_EMAIL_THEME_ID]: { displayName: 'Default Light', tsxSource: LightEmailTheme, }, "a0172b5d-cff0-463b-83bb-85124697373a": { displayName: 'Default Dark', tsxSource: DarkEmailTheme, }, "c7e2d94f-8a1b-4e6d-b3f5-9d0a2e7c1b8f": { displayName: 'Default Colorful', tsxSource: ColorfulEmailTheme, }, }; const EMAIL_TEMPLATE_EMAIL_VERIFICATION_ID = "e7d009ce-8d47-4528-b245-5bf119f2ffa3"; const EMAIL_TEMPLATE_PASSWORD_RESET_ID = "a70fb3a4-56c1-4e42-af25-49d25603abd0"; const EMAIL_TEMPLATE_MAGIC_LINK_ID = "822687fe-8d0a-4467-a0d1-416b6e639478"; const EMAIL_TEMPLATE_TEAM_INVITATION_ID = "e84de395-2076-4831-9c19-8e9a96a868e4"; const EMAIL_TEMPLATE_SIGN_IN_INVITATION_ID = "066dd73c-36da-4fd0-b6d6-ebf87683f8bc"; const EMAIL_TEMPLATE_PAYMENT_RECEIPT_ID = "70372aee-0441-4d80-974c-2e858e40123a"; const EMAIL_TEMPLATE_PAYMENT_FAILED_ID = "f64b1afe-27ec-4a28-a277-7178f3261f9a"; const EMAIL_TEMPLATE_TRIAL_WILL_END_ID = "c3f8a1d2-7e4b-4a91-b2c5-9e8f1a0d3b6c"; export const DEFAULT_EMAIL_TEMPLATES = { [EMAIL_TEMPLATE_EMAIL_VERIFICATION_ID]: { "displayName": "Email Verification", "tsxSource": "import { type } from \"arktype\"\nimport { Button, Section, Hr, Text, Heading } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\nexport const variablesSchema = type({\n emailVerificationLink: \"string\"\n})\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n \n Verify your email at {project.displayName}\n \n

\n Hi{user.displayName ? (\", \" + user.displayName) : ''}! Please click on the following button to verify your email.\n

\n
\n \n Verify my email\n \n
\n
\n
\n
\n

\n If you were not expecting this email, you can safely ignore it. \n

\n
\n
\n \n )\n}\n\nEmailTemplate.PreviewVariables = {\n emailVerificationLink: \"#\"\n} satisfies typeof variablesSchema.infer", "themeId": undefined, }, [EMAIL_TEMPLATE_PASSWORD_RESET_ID]: { "displayName": "Password Reset", "tsxSource": "import { type } from \"arktype\"\nimport { Button, Section, Hr, Text, Heading } from \"@react-email/components\"\nimport { Subject, NotificationCategory, Props} from \"@stackframe/emails\"\n\nexport const variablesSchema = type({\n passwordResetLink: \"string\"\n})\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n \n Reset your password at {project.displayName}\n \n\n

\n Hi{user.displayName ? (\", \" + user.displayName) : \"\"}! Please click on the following button to start the password reset process.\n

\n\n
\n \n Reset my password\n \n
\n\n
\n
\n
\n\n

\n If you were not expecting this email, you can safely ignore it.\n

\n
\n
\n \n )\n}\n\nEmailTemplate.PreviewVariables = {\n passwordResetLink: \"#\"\n} satisfies typeof variablesSchema.infer", "themeId": undefined, }, [EMAIL_TEMPLATE_MAGIC_LINK_ID]: { "displayName": "Magic Link/OTP", "tsxSource": "import { type } from 'arktype';\nimport { Section, Hr, Text, Heading } from '@react-email/components';\nimport { Subject, NotificationCategory, Props } from '@stackframe/emails';\n\nexport const variablesSchema = type({\n magicLink: 'string',\n otp: 'string',\n});\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n \n Sign in to {project.displayName}\n \n

\n Hi{user.displayName ? \", \" + user.displayName : \"\"}! This is your one-time-password for signing in:\n

\n

\n {variables.otp}\n

\n

\n Or you can click on{' '}\n \n this link\n {' '}\n to sign in\n

\n
\n

\n If you were not expecting this email, you can safely ignore it.\n

\n
\n
\n \n );\n}\n\nEmailTemplate.PreviewVariables = {\n magicLink: \"#\",\n otp: \"3SLSWZ\"\n} satisfies typeof variablesSchema.infer", "themeId": undefined, }, [EMAIL_TEMPLATE_TEAM_INVITATION_ID]: { "displayName": "Team Invitation", "tsxSource": "import { type } from \"arktype\";\nimport { Button, Section, Hr, Text, Heading } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\n\nexport const variablesSchema = type({\n teamDisplayName: \"string\",\n teamInvitationLink: \"string\"\n});\n\nexport function EmailTemplate({ user, variables }: Props) {\n return (\n <>\n \n \n
\n
\n \n You are invited to {variables.teamDisplayName}\n \n

\n Hi{user.displayName ? \", \" + user.displayName : \"\"}! Please click the button below to join the team {variables.teamDisplayName}\n

\n
\n \n Join team\n \n
\n
\n
\n
\n

\n If you were not expecting this email, you can safely ignore it.\n

\n
\n
\n \n );\n}\n\nEmailTemplate.PreviewVariables = {\n teamDisplayName: \"My Team\",\n teamInvitationLink: \"#\"\n} satisfies typeof variablesSchema.infer ", "themeId": undefined, }, [EMAIL_TEMPLATE_SIGN_IN_INVITATION_ID]: { "displayName": "Sign In Invitation", "tsxSource": "import { type } from \"arktype\"\nimport { Button, Section, Hr, Text, Heading } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\nexport const variablesSchema = type({\n signInInvitationLink: \"string\",\n teamDisplayName: \"string\"\n})\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n\n
\n
\n \n You are invited to sign in to {variables.teamDisplayName}\n \n\n

\n Hi\n {user.displayName ? \", \" + user.displayName : \"\"}! Please click on the following\n link to sign in to your account\n

\n\n
\n \n Sign in\n \n
\n\n
\n
\n
\n\n

\n If you were not expecting this email, you can safely ignore it.\n

\n
\n
\n \n )\n}\n\nEmailTemplate.PreviewVariables = {\n signInInvitationLink: \"#\",\n teamDisplayName: \"My Team\"\n} satisfies typeof variablesSchema.infer", "themeId": undefined, }, [EMAIL_TEMPLATE_PAYMENT_RECEIPT_ID]: { "displayName": "Payment Receipt", "tsxSource": "import { type } from \"arktype\";\nimport { Button, Section, Hr } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\nexport const variablesSchema = type({\n productName: \"string\",\n quantity: \"number\",\n amount: \"string\",\n receiptLink: \"string?\"\n});\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n

\n Thanks for your purchase\n

\n

\n Hi{user.displayName ? (\", \" + user.displayName) : \"\"}! Your payment for {variables.productName} is complete.\n

\n
\n

\n Total paid: {variables.amount}\n

\n

\n Quantity: {variables.quantity}\n

\n
\n {variables.receiptLink ? (\n
\n \n View receipt\n \n
\n ) : null}\n
\n
\n
\n
\n
\n \n );\n}\n\nEmailTemplate.PreviewVariables = {\n productName: \"Pro Plan\",\n quantity: 1,\n amount: \"$29.00\",\n receiptLink: \"https://example.com/receipt\"\n} satisfies typeof variablesSchema.infer;\n", "themeId": undefined, }, [EMAIL_TEMPLATE_PAYMENT_FAILED_ID]: { "displayName": "Payment Failed", "tsxSource": "import { type } from \"arktype\";\nimport { Button, Section, Hr } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\nexport const variablesSchema = type({\n productName: \"string\",\n amount: \"string\",\n invoiceUrl: \"string?\",\n failureReason: \"string?\"\n});\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n

\n We couldn't process your payment\n

\n

\n Hi{user.displayName ? (\", \" + user.displayName) : \"\"}! Your payment for {variables.productName} ({variables.amount}) did not go through.\n

\n {variables.failureReason ? (\n

\n Reason: {variables.failureReason}\n

\n ) : null}\n {variables.invoiceUrl ? (\n
\n \n View invoice\n \n
\n ) : null}\n
\n
\n
\n

\n Please update your payment details to avoid service interruption.\n

\n
\n
\n \n );\n}\n\nEmailTemplate.PreviewVariables = {\n productName: \"Pro Plan\",\n amount: \"$29.00\",\n invoiceUrl: \"https://example.com/billing\",\n failureReason: \"Your card was declined\"\n} satisfies typeof variablesSchema.infer;\n", "themeId": undefined, }, [EMAIL_TEMPLATE_TRIAL_WILL_END_ID]: { "displayName": "Trial Ending Soon", "tsxSource": "import { type } from \"arktype\";\nimport { Section, Hr } from \"@react-email/components\";\nimport { Subject, NotificationCategory, Props } from \"@stackframe/emails\";\n\nexport const variablesSchema = type({\n productName: \"string\",\n trialEndDate: \"string\",\n});\n\nexport function EmailTemplate({ user, project, variables }: Props) {\n return (\n <>\n \n \n
\n
\n

\n Your free trial is ending soon\n

\n

\n Hi{user.displayName ? (\", \" + user.displayName) : \"\"}! Your free trial of {variables.productName} at {project.displayName} ends on {variables.trialEndDate}.\n

\n

\n After that, your payment method on file will be charged for the subscription.\n

\n
\n
\n
\n
\n
\n \n );\n}\n\nEmailTemplate.PreviewVariables = {\n productName: \"Pro Plan\",\n trialEndDate: \"January 15, 2026\",\n} satisfies typeof variablesSchema.infer;\n", "themeId": undefined, } }; export const DEFAULT_TEMPLATE_IDS = { email_verification: EMAIL_TEMPLATE_EMAIL_VERIFICATION_ID, password_reset: EMAIL_TEMPLATE_PASSWORD_RESET_ID, magic_link: EMAIL_TEMPLATE_MAGIC_LINK_ID, team_invitation: EMAIL_TEMPLATE_TEAM_INVITATION_ID, sign_in_invitation: EMAIL_TEMPLATE_SIGN_IN_INVITATION_ID, payment_receipt: EMAIL_TEMPLATE_PAYMENT_RECEIPT_ID, payment_failed: EMAIL_TEMPLATE_PAYMENT_FAILED_ID, trial_will_end: EMAIL_TEMPLATE_TRIAL_WILL_END_ID, } as const;