### Complete Document System Example Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Demonstrates the full setup of a custom document system, including defining block schemas, React components, building the block dictionary, and rendering documents. ```typescript import { buildBlockComponent, buildBlockConfigurationSchema, buildBlockConfigurationDictionary, BlockConfiguration, } from '@usewaypoint/document-core'; import { z } from 'zod'; import React from 'react'; // 1. Define schemas for each block type const TextBlockSchema = z.object({ content: z.string(), size: z.enum(['small', 'medium', 'large']).optional(), }); const ButtonBlockSchema = z.object({ label: z.string(), onClick: z.string(), // action name }); const ImageBlockSchema = z.object({ src: z.string(), alt: z.string(), }); // 2. Define React components for each block function TextBlock({ content, size }: z.infer) { const sizeClass = { small: 'text-sm', medium: 'text-base', large: 'text-lg', }[size ?? 'medium']; return
{content}
; } function ButtonBlock({ label, onClick }: z.infer) { return ; } function ImageBlock({ src, alt }: z.infer) { return {alt}; } // 3. Create the block dictionary const blockDict = buildBlockConfigurationDictionary({ Text: { schema: TextBlockSchema, Component: TextBlock, }, Button: { schema: ButtonBlockSchema, Component: ButtonBlock, }, Image: { schema: ImageBlockSchema, Component: ImageBlock, }, }); // 4. Build schema and component const blockSchema = buildBlockConfigurationSchema(blockDict); type BlockType = z.infer; const BlockRenderer = buildBlockComponent(blockDict); // 5. Create document type type Document = Record; // 6. Use in components export function DocumentViewer({ doc, rootId }: { doc: Document; rootId: string }) { const block = doc[rootId]; if (!block) throw new Error(`Block ${rootId} not found`); return ; } // 7. Example usage const myDoc: Document = { root: { type: 'Text', data: { content: 'Hello World', size: 'large' }, }, button: { type: 'Button', data: { label: 'Click me', onClick: 'handleClick' }, }, }; export default function App() { return ; } ``` -------------------------------- ### Install Dependencies and Run Vite Server Source: https://github.com/usewaypoint/email-builder-js/blob/main/examples/vite-emailbuilder-mui/README.md Install project dependencies using npm and start the Vite development server. Access the application at http://localhost:5173/email-builder-js/. ```bash cd examples/vite-emailbuilder-mui npm install npx vite ``` -------------------------------- ### Install EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/README.md Install the EmailBuilder.js package using npm. ```bash npm install --save @usewaypoint/email-builder ``` -------------------------------- ### Install Document Core Source: https://github.com/usewaypoint/email-builder-js/blob/main/packages/document-core/README.md Install the document-core package using npm. ```bash npm install --save @usewaypoint/document-core ``` -------------------------------- ### Create Custom Block Example Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md A concise example demonstrating the creation of a custom block using `buildBlockConfigurationDictionary` from '@usewaypoint/document-core'. It shows how to define a schema and associate a component. ```typescript import { buildBlockComponent, buildBlockConfigurationSchema, buildBlockConfigurationDictionary } from '@usewaypoint/document-core'; const dict = buildBlockConfigurationDictionary({ MyBlock: { schema: z.object({ /* ... */ }), Component: MyComponent, }, }); ``` -------------------------------- ### Install EmailBuilder.js and Peer Dependencies Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Install the EmailBuilder.js package and its required peer dependencies using npm. ```bash npm install @usewaypoint/email-builder npm install react react-dom zod ``` -------------------------------- ### EmailBuilder.js Configuration Example Source: https://github.com/usewaypoint/email-builder-js/blob/main/README.md An example of a TReaderDocument configuration object for EmailBuilder.js. ```javascript import { TReaderDocument } from '@usewaypoint/email-builder'; const CONFIGURATION: TReaderDocument = { root: { type: 'EmailLayout', data: { backdropColor: '#F8F8F8', canvasColor: '#FFFFFF', textColor: '#242424', fontFamily: 'MODERN_SANS', childrenIds: ['block-1709578146127'], }, }, 'block-1709578146127': { type: 'Text', data: { style: { fontWeight: 'normal', padding: { top: 16, bottom: 16, right: 24, left: 24, }, }, props: { text: 'Hello world', }, }, }, }; ``` -------------------------------- ### Example EmailLayout Configuration Object Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Illustrates how to configure the EmailLayout block with specific styling properties. This example sets custom colors, a default font, and specifies child block IDs. ```typescript const emailLayout = { type: 'EmailLayout', data: { backdropColor: '#F8F8F8', // Light gray outer area canvasColor: '#FFFFFF', // White email content area textColor: '#1a1a1a', // Dark text by default fontFamily: 'MODERN_SANS', // Default to modern sans font borderColor: '#CCCCCC', // Subtle border borderRadius: 8, // Slightly rounded corners childrenIds: ['block-1', 'block-2'], }, }; ``` -------------------------------- ### Container Component Example Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md Illustrates how to use the Container component with specific background color and internal padding. ```typescript ``` -------------------------------- ### Project Package Structure Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Illustrates the directory layout of the email-builder-js project. It shows the main email-builder package, core utilities, individual block packages, and an examples directory. ```text email-builder-js/ ├── packages/ │ ├── email-builder/ # Main package (public) │ ├── document-core/ # Core utilities (public) │ ├── block-avatar/ # Avatar block │ ├── block-button/ # Button block │ ├── block-columns-container/ # Columns layout │ ├── block-container/ # Container block │ ├── block-divider/ # Divider block │ ├── block-heading/ # Heading block │ ├── block-html/ # HTML block │ ├── block-image/ # Image block │ ├── block-spacer/ # Spacer block │ └── block-text/ # Text block └── examples/ # Example applications ``` -------------------------------- ### ColumnsContainer Component Example Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md Demonstrates the usage of ColumnsContainer to create a two-column layout with specified background color, padding, and gap between columns. ```typescript ], [], ]} /> ``` -------------------------------- ### Server-Side Email Rendering with EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Example of rendering an email template server-side for sending transactional emails. Assumes an email service is configured. ```typescript // api/send-welcome-email.ts import { renderToStaticMarkup, TReaderDocument } from '@usewaypoint/email-builder'; const welcomeTemplate: TReaderDocument = { /* ... template config ... */ }; export async function sendWelcomeEmail(userEmail: string) { const html = renderToStaticMarkup(welcomeTemplate, { rootBlockId: 'root' }); return await emailService.send({ to: userEmail, subject: 'Welcome to our platform', html: html, }); ``` -------------------------------- ### TypeScript Type Mismatch Examples Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/errors.md Illustrates common TypeScript compile-time errors due to type mismatches in block data. These examples highlight incorrect property assignments and type coercions. ```typescript // Property 'unknown' does not exist on type 'TReaderBlock' const block: TReaderBlock = { type: 'Text', data: { unknown: true, // TS Error 2345 }, }; // fontSize must be number, not string const block: TReaderBlock = { type: 'Text', data: { style: { fontSize: 'large', // TS Error 2322 }, }, }; ``` -------------------------------- ### Nodemailer sendMail Integration Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/errors.md Shows how to send an email using nodemailer after rendering the document to a static HTML string. This example focuses on the correct usage of the `sendMail` function. ```typescript const nodemailer = require('nodemailer'); const html = renderToStaticMarkup(document, { rootBlockId: 'root' }); try { await transporter.sendMail({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Subject', html: html, // Must be string, not JSX element }); } catch (error) { // sendMail errors - not related to EmailBuilder console.error('Email send failed:', error.message); } ``` -------------------------------- ### Peer Dependencies Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Lists the essential peer dependencies required for email-builder-js, including specific version ranges for React and Zod. Ensure these are installed in your project. ```json { "react": "^16 || ^17 || ^18", "react-dom": "^16 || ^17 || ^18", "zod": "^1 || ^2 || ^3" } ``` -------------------------------- ### Send Rendered Email via Service Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Provides a basic example of sending an email after it has been rendered to HTML. This snippet assumes an `emailService` object with a `send` method. ```typescript const html = renderToStaticMarkup(document, { rootBlockId: 'root' }); await emailService.send({ to: 'user@example.com', subject: 'Subject', html: html, }); ``` -------------------------------- ### Send Email using Nodemailer Source: https://github.com/usewaypoint/email-builder-js/blob/main/README.md Example of sending an email with an HTML body generated by EmailBuilder.js using Nodemailer. ```javascript import { renderToStaticMarkup } from '@usewaypoint/email-builder'; import nodemailer from "nodemailer"; // Replace this with your transport configuration const transportConfig = {} const transporter = nodemailer.createTransport(transportConfig); // Replace this with the JSON for your Reader document const CONFIGURATION: TReaderDocument = {} await transporter.sendMail({ from: 'no-reply@example.com' to: 'friend@example.com', subject: 'Hello', html: renderToStaticMarkup(CONFIGURATION, { rootBlockId: 'root' }), }); ``` -------------------------------- ### Send Email using Waypoint API Source: https://github.com/usewaypoint/email-builder-js/blob/main/README.md Example of sending an email with an HTML body generated by EmailBuilder.js using the Waypoint API. ```javascript import axios from 'axios'; import { renderToStaticMarkup } from '@usewaypoint/email-builder'; // Replace this with the JSON for your Reader document const CONFIGURATION: TReaderDocument = {} await axios({ method: 'post', url: 'https://live.waypointapi.com/v1/email_messages', headers: { 'Content-Type': 'application/json', }, auth: { username: API_KEY_USERNAME, password: API_KEY_PASSWORD, }, data: { from: 'no-reply@example.com' to: 'friend@example.com', subject: 'Hello', bodyHtml: renderToStaticMarkup(CONFIGURATION, { rootBlockId: 'root' }), }, }); ``` -------------------------------- ### Basic Email Rendering with EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Demonstrates how to use the `Reader` component for client-side rendering and `renderToStaticMarkup` for server-side HTML generation with a sample email configuration. ```typescript import { Reader, renderToStaticMarkup, TReaderDocument } from '@usewaypoint/email-builder'; const emailConfig: TReaderDocument = { root: { type: 'EmailLayout', data: { canvasColor: '#FFFFFF', textColor: '#000000', childrenIds: ['text-1'], }, }, 'text-1': { type: 'Text', data: { props: { text: 'Hello World' }, }, }, }; // Render to HTML string (server-side) const html = renderToStaticMarkup(emailConfig, { rootBlockId: 'root' }); // Or render React component (client-side) ``` -------------------------------- ### Example of Invalid Block Data Shape Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/errors.md An example demonstrating a block with an incorrect data shape, specifically an invalid type for the 'fontSize' property, which would trigger a ZodError during schema parsing. ```typescript const invalidBlock = { type: 'Text', data: { props: { text: 'Hello', fontSize: 'not-a-number', // Should be number or undefined }, }, }; ReaderBlockSchema.parse(invalidBlock); // Throws ZodError ``` -------------------------------- ### Basic Email Rendering with EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Demonstrates the basic usage of EmailBuilder.js to create an email document structure and render it to an HTML string. ```typescript import { Reader, renderToStaticMarkup, TReaderDocument } from '@usewaypoint/email-builder'; // 1. Create document structure const emailConfig: TReaderDocument = { root: { type: 'EmailLayout', data: { backdropColor: '#F5F5F5', canvasColor: '#FFFFFF', textColor: '#000000', fontFamily: 'MODERN_SANS', childrenIds: ['heading', 'content'], }, }, heading: { type: 'Heading', data: { props: { text: 'Welcome!', level: 'h1', }, style: { textAlign: 'center', color: '#1a1a1a', }, }, }, content: { type: 'Text', data: { props: { text: 'Thanks for joining us.', }, style: { padding: { top: 16, bottom: 16, left: 24, right: 24 }, }, }, }, }; // 2. Render to HTML string const html = renderToStaticMarkup(emailConfig, { rootBlockId: 'root' }); // 3. Send via email service await sendEmail({ to: 'user@example.com', subject: 'Welcome', html: html, }); ``` -------------------------------- ### Configure ColumnsContainer Layout Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Set up multi-column layouts (2 or 3 columns) with configurable gaps between columns and vertical content alignment. Optional fixed widths for each column can also be specified. ```typescript { type: 'ColumnsContainer', data: { style: { backgroundColor: '#FFFFFF', padding: { top: 20, bottom: 20, left: 20, right: 20 }, }, props: { columnsCount: 2, // 2 or 3 columns columnsGap: 20, // Gap between columns in pixels contentAlignment: 'middle', // 'top' | 'middle' | 'bottom' fixedWidths: [200, 200, null], // Optional fixed column widths }, }, } ``` -------------------------------- ### Extensibility Pattern for Adding Blocks Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Demonstrates how to extend existing block dictionaries by merging base blocks with new custom blocks, promoting modularity. ```typescript // In email-builder const baseBlocks = buildBlockConfigurationDictionary({ Text: { /* ... */ }, Button: { /* ... */ }, }); // In extending library const extendedBlocks = buildBlockConfigurationDictionary({ ...baseBlocks, CustomBlock: { /* ... */ }, }); ``` -------------------------------- ### Creating Custom Blocks with Document Core Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Demonstrates how to extend email-builder-js by creating custom blocks using utilities from '@usewaypoint/document-core'. This involves defining schemas and components. ```typescript import { buildBlockComponent, buildBlockConfigurationSchema } from '@usewaypoint/document-core'; const customBlocks = buildBlockConfigurationDictionary({ // ... existing blocks CustomBlock: { schema: z.object({ /* ... */ }), Component: CustomComponent, }, }); const schema = buildBlockConfigurationSchema(customBlocks); const BlockRenderer = buildBlockComponent(customBlocks); ``` -------------------------------- ### buildBlockComponent Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Creates a React component that renders block configurations from a dictionary. This component dynamically selects and renders the correct UI for each block type based on its configuration. ```APIDOC ## buildBlockComponent ### Description Creates a React component that renders block configurations from a dictionary. This component dynamically selects and renders the correct UI for each block type based on its configuration. ### Function Signature ```typescript function buildBlockComponent( blocks: DocumentBlocksDictionary ): (props: BlockConfiguration) => JSX.Element ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **blocks** (DocumentBlocksDictionary) - Required - Same dictionary used for schema building. Maps block types to React components. ### Request Example ```typescript import { buildBlockComponent } from '@usewaypoint/document-core'; const blockDict = { Text: { schema: z.object({ content: z.string() }), Component: ({ content }) =>

{content}

, }, Image: { schema: z.object({ src: z.string() }), Component: ({ src }) => , }, }; const BlockRenderer = buildBlockComponent(blockDict); // Use in component function MyEmail() { const block = { type: 'Text' as const, data: { content: 'Hello' }, }; return ; } ``` ### Response #### Success Response * **React component function** - A component that accepts a `BlockConfiguration` object and renders the appropriate component from the dictionary based on the `type` field. #### Response Example (A React component function, not a data example) **Implementation:** Looks up `blocks[type].Component` and renders it with the `data` props. ``` -------------------------------- ### Image Component Configuration Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md Configure an Image component with dimensions, source URL, alt text, and optional linking. Suitable for displaying product images or other visual content. ```typescript function Image(props: ImageProps): JSX.Element interface ImageProps { style?: { padding?: PaddingObject; backgroundColor?: ColorString | null; textAlign?: 'center' | 'left' | 'right' | null; } | null; props?: { width?: number | null; height?: number | null; url?: string | null; alt?: string | null; linkHref?: string | null; contentAlignment?: 'top' | 'middle' | 'bottom' | null; } | null; } ``` ```typescript ``` -------------------------------- ### Build Block Component Source: https://github.com/usewaypoint/email-builder-js/blob/main/packages/document-core/README.md Use the `buildBlockComponent` function with your dictionary to create a component for rendering blocks. This component accepts a 'type' and 'data' prop. ```typescript const Block = buildBlockComponent(dictionary); ``` -------------------------------- ### Supported Block Types Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Demonstrates the correct usage of block types. Invalid types will cause an error, so ensure you use one of the supported types. ```typescript // ✗ InvalidType is not supported { type: 'InvalidType', data: {} } ``` ```typescript // ✓ Use supported types { type: 'Text', data: { /* ... */ } } ``` -------------------------------- ### buildBlockConfigurationDictionary Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md This function types a DocumentBlocksDictionary at compile time, ensuring proper type inference for generic type parameters. It takes a dictionary mapping block type names to their schemas and components and returns the same dictionary with enhanced type information. ```APIDOC ## buildBlockConfigurationDictionary ### Description Identity function that types a DocumentBlocksDictionary at compile time. It helps TypeScript's type inference system properly understand the structure of the dictionary and infer the correct generic types for downstream function calls. ### Function Signature ```typescript function buildBlockConfigurationDictionary( blocks: DocumentBlocksDictionary ): DocumentBlocksDictionary ``` ### Parameters #### Parameters - **blocks** (DocumentBlocksDictionary) - Required - Dictionary mapping block type names to schema and component pairs. ### Returns DocumentBlocksDictionary Returns the input dictionary unchanged, but with full type inference for generic type parameter `T`. ### Example ```typescript import { buildBlockConfigurationDictionary } from '@usewaypoint/document-core'; import { z } from 'zod'; // Without buildBlockConfigurationDictionary, TypeScript might not // properly infer all the block types for downstream type checking const blocks = buildBlockConfigurationDictionary({ Text: { schema: z.object({ content: z.string() }), Component: TextBlock, }, Image: { schema: z.object({ src: z.string() }), Component: ImageBlock, }, }); // Now the dictionary is properly typed for use with buildBlockComponent // and buildBlockConfigurationSchema const schema = buildBlockConfigurationSchema(blocks); const Component = buildBlockComponent(blocks); ``` ``` -------------------------------- ### Render EmailBuilder.js Configuration to HTML String Source: https://github.com/usewaypoint/email-builder-js/blob/main/README.md Use the renderToStaticMarkup function to convert an EmailBuilder.js configuration into an HTML string. ```javascript import { renderToStaticMarkup } from '@usewaypoint/email-builder'; const string = renderToStaticMarkup(CONFIGURATION, { rootBlockId: 'root' }); ``` -------------------------------- ### Basic CSS Styling for EmailBuilder Source: https://github.com/usewaypoint/email-builder-js/blob/main/examples/vite-emailbuilder-mui/index.html This snippet shows basic CSS styling for the EmailBuilder application, setting margins, height, and width for html, body, and #root elements to ensure full viewport coverage. ```html html { margin: 0px; height: 100vh; width: 100%; } body { min-height: 100vh; width: 100%; } #root { height: 100vh; width: 100%; } ``` -------------------------------- ### Html Component Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md Injects raw HTML content into the application. Use with caution as it renders HTML directly. ```APIDOC ## Html Component ### Description Injects raw HTML content into the application. Use with caution as it renders HTML directly. ### Props #### `style` object - **`color`** (ColorString) - Optional - Default: 'inherit'. Text color. - **`backgroundColor`** (ColorString) - Optional - Background color. - **`fontFamily`** (FontFamily) - Optional - Default: 'inherit'. Font family. - **`fontSize`** (number) - Optional - Font size. - **`textAlign`** (string) - Optional - Default: 'left'. Alignment ('left', 'right', 'center'). - **`padding`** (PaddingObject) - Optional - Padding around the HTML content. #### `props` object - **`contents`** (string) - Optional - Default: undefined. Raw HTML string to inject. ### Example ```typescript Custom HTML', }} /> ``` ### Security Note HTML is rendered with `dangerouslySetInnerHTML`. Only use with trusted content. Sanitize user input before passing to this block. ``` -------------------------------- ### Build Block Component for Rendering Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Creates a React component that dynamically renders different block types based on a configuration object. Pass the same block dictionary used for schema building to this function. Use the returned component to render your document blocks in a React application. ```typescript import { buildBlockComponent } from '@usewaypoint/document-core'; const blockDict = { Text: { schema: z.object({ content: z.string() }), Component: ({ content }) =>

{content}

, }, Image: { schema: z.object({ src: z.string() }), Component: ({ src }) => , }, }; const BlockRenderer = buildBlockComponent(blockDict); // Use in component function MyEmail() { const block = { type: 'Text' as const, data: { content: 'Hello' }, }; return ; } ``` -------------------------------- ### Registering Custom Block in Reader Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Shows how to register a custom block (e.g., 'Custom') with its schema and component into the Reader's dictionary. ```typescript import { Custom, CustomPropsSchema } from '@usewaypoint/block-custom'; const READER_DICTIONARY = buildBlockConfigurationDictionary({ // ... existing blocks Custom: { schema: CustomPropsSchema, Component: Custom, }, }); ``` -------------------------------- ### Render Email Document to HTML Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Shows how to convert an email document object into a static HTML string using the `renderToStaticMarkup` function from '@usewaypoint/email-builder'. ```typescript import { renderToStaticMarkup } from '@usewaypoint/email-builder'; const html = renderToStaticMarkup(document, { rootBlockId: 'root' }); // Returns: "....." ``` -------------------------------- ### Container Component Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md A versatile container block for structuring content with customizable styling options. ```APIDOC ## Container Component ### Description A versatile container block for structuring content with customizable styling options. ### Props #### `style` object - **`backgroundColor`** (ColorString) - Optional - Background color of the container. - **`borderColor`** (ColorString) - Optional - Border color of the container (1px solid). - **`borderRadius`** (number) - Optional - Border radius in pixels. - **`padding`** (PaddingObject) - Optional - Internal padding of the container. #### `children` - **`children`** (JSX.Element | JSX.Element[]) - Optional - Child elements to be rendered inside the container. ### Example ```jsx ``` ``` -------------------------------- ### Build Block Configuration Schema Source: https://github.com/usewaypoint/email-builder-js/blob/main/packages/document-core/README.md Use `buildBlockConfigurationSchema` with your dictionary to generate a Zod schema for validating block configurations. This schema can then be used for parsing and validation. ```typescript const Schema = buildBlockConfigurationSchema(dictionary); const parsedData = Schema.safeParse({ type: 'Alert', data: { message: 'Hello World' }, }); ``` -------------------------------- ### Snapshot Test Email Rendering Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Perform snapshot testing on rendered emails to ensure consistency. This requires importing renderToStaticMarkup from '@usewaypoint/email-builder'. ```typescript import { renderToStaticMarkup } from '@usewaypoint/email-builder'; describe('Email Templates', () => { it('renders welcome email', () => { const html = renderToStaticMarkup(document, { rootBlockId: 'root' }); expect(html).toMatchSnapshot(); }); }); ``` -------------------------------- ### Define Document Block Dictionary Source: https://github.com/usewaypoint/email-builder-js/blob/main/packages/document-core/README.md Create a dictionary mapping block names to their Zod schemas and React components. This is the root of the library's functionality. ```typescript const dictionary = { Alert: { schema: z.object({ message: z.string(), }), Component: ({ message }: { message: string }) => { return
{message.toUpperCase()}
} } } ``` -------------------------------- ### Render Email with SendGrid Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/email-builder.md Renders an email template to HTML and sends it using SendGrid. Ensure your SENDGRID_API_KEY environment variable is set. ```typescript import { renderToStaticMarkup, TReaderDocument } from '@usewaypoint/email-builder'; import sgMail from '@sendgrid/mail'; sgMail.setApiKey(process.env.SENDGRID_API_KEY); const template: TReaderDocument = { /* ... template config ... */ }; const html = renderToStaticMarkup(template, { rootBlockId: 'root' }); await sgMail.send({ to: 'user@example.com', from: 'noreply@example.com', subject: 'Your Email Subject', html: html, }); ``` -------------------------------- ### Cache Rendered HTML with NodeCache Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Implements HTML rendering with caching using NodeCache to improve performance by storing previously rendered templates. Cache entries have a default TTL of 1 hour. ```typescript import NodeCache from 'node-cache'; import { renderToStaticMarkup } from '@usewaypoint/email-builder'; const cache = new NodeCache({ stdTTL: 3600 }); // 1 hour export function renderTemplateWithCache( templateId: string, variables?: object ): string { const cacheKey = `${templateId}:${JSON.stringify(variables)}`; const cached = cache.get(cacheKey); if (cached) return cached; const template = loadTemplateSync(templateId); const doc = interpolateDocument(template, variables); const html = renderToStaticMarkup(doc, { rootBlockId: 'root' }); cache.set(cacheKey, html); return html; } ``` -------------------------------- ### Type-Safe Block Rendering Pattern Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Illustrates the type safety achieved by linking Zod schemas, React components, and block configurations using builder functions. ```typescript // Schema defines shape const MySchema = z.object({ text: z.string() }); // Component consumes that shape function MyComponent(props: z.infer) { /* ... */ } // Dictionary ties them together const dict = { MyBlock: { schema: MySchema, Component: MyComponent } }; // Schema validation guarantees type safety const schema = buildBlockConfigurationSchema(dict); const block = schema.parse(untrustedData); // Type is BlockConfiguration const renderer = buildBlockComponent(dict); // TypeScript knows this is safe ``` -------------------------------- ### Main Exports from EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Lists the primary components, types, and schemas exported by the EmailBuilder.js library for use in projects. ```typescript // Components export { Reader } // React component export { ReaderBlock } // Lower-level block renderer export { default as renderToStaticMarkup } // HTML string renderer // Types export type { TReaderDocument } // Document type export type { TReaderBlock } // Block configuration export type { TReaderProps } // Reader component props export type { TReaderBlockProps } // ReaderBlock component props // Schemas export { ReaderBlockSchema } // Zod schema for blocks export { ReaderDocumentSchema } // Zod schema for documents ``` -------------------------------- ### Configure Button Block Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Style button blocks with custom background colors, font properties, alignment, and padding. Configure button text, URL, size, style, and background/text colors. Full width option is available. ```typescript { type: 'Button', data: { style: { backgroundColor: '#F0F0F0', // Wrapper background fontSize: 16, fontFamily: 'MODERN_SANS', fontWeight: 'bold', textAlign: 'center', padding: { top: 20, bottom: 20, left: 20, right: 20 }, }, props: { text: 'Click Here', url: 'https://example.com', size: 'medium', // 'x-small' | 'small' | 'medium' | 'large' buttonStyle: 'rounded', // 'rectangle' | 'rounded' | 'pill' buttonBackgroundColor: '#0066CC', buttonTextColor: '#FFFFFF', fullWidth: false, }, }, } ``` -------------------------------- ### Email Builder Data Flow Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/README.md Outlines the data processing pipeline from an initial JSON document to the final HTML output. It includes steps like Zod validation, component rendering, and block lookup. ```text JSON Document (TReaderDocument) ↓ Zod Validation (ReaderBlockSchema) ↓ Reader Component / renderToStaticMarkup ↓ Block Dictionary Lookup ↓ Individual Block Components ↓ HTML Output (React tree or HTML string) ``` -------------------------------- ### Build Block Configuration Dictionary Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/document-core.md Use this function to type a DocumentBlocksDictionary at compile time. It helps TypeScript infer generic types correctly for downstream functions. ```typescript function buildBlockConfigurationDictionary( blocks: DocumentBlocksDictionary ): DocumentBlocksDictionary ``` ```typescript import { buildBlockConfigurationDictionary } from '@usewaypoint/document-core'; import { z } from 'zod'; // Without buildBlockConfigurationDictionary, TypeScript might not // properly infer all the block types for downstream type checking const blocks = buildBlockConfigurationDictionary({ Text: { schema: z.object({ content: z.string() }), Component: TextBlock, }, Image: { schema: z.object({ src: z.string() }), Component: ImageBlock, }, }); // Now the dictionary is properly typed for use with buildBlockComponent // and buildBlockConfigurationSchema const schema = buildBlockConfigurationSchema(blocks); const Component = buildBlockComponent(blocks); ``` -------------------------------- ### Configure Container Styling Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Individual containers can be styled with custom background colors, padding, border radius, and border colors. Padding can be set for top, bottom, left, and right. ```typescript { type: 'Container', data: { style: { backgroundColor: '#F0F0F0', padding: { top: 20, bottom: 20, left: 20, right: 20, }, borderRadius: 4, borderColor: '#CCCCCC', }, props: { childrenIds: ['inner-block-1'], }, }, } ``` -------------------------------- ### Client-Side Email Preview with EmailBuilder.js Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Component for rendering an EmailBuilder.js document client-side, useful for live previews within an application. ```typescript // components/EmailPreview.tsx import { Reader, TReaderDocument } from '@usewaypoint/email-builder'; interface EmailPreviewProps { document: TReaderDocument; } export function EmailPreview({ document }: EmailPreviewProps) { return (
); } ``` -------------------------------- ### File-Based Email Templates Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/integration-guide.md Provides functions to load and save email templates as JSON files. Assumes templates are stored in an 'email-templates' directory. ```typescript import fs from 'fs/promises'; import path from 'path'; import { TReaderDocument } from '@usewaypoint/email-builder'; const TEMPLATE_DIR = path.join(process.cwd(), 'email-templates'); export async function loadTemplate(name: string): Promise { const filePath = path.join(TEMPLATE_DIR, `${name}.json`); const content = await fs.readFile(filePath, 'utf-8'); return JSON.parse(content); } export async function saveTemplate(name: string, doc: TReaderDocument) { const filePath = path.join(TEMPLATE_DIR, `${name}.json`); await fs.writeFile(filePath, JSON.stringify(doc, null, 2)); } // Usage const welcomeTemplate = await loadTemplate('welcome'); const html = renderToStaticMarkup(welcomeTemplate, { rootBlockId: 'root' }); ``` -------------------------------- ### EmailLayout Block Configuration Interface Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/configuration.md Defines the properties available for configuring the root EmailLayout block, which controls global email styling. These properties manage aspects like background colors, text styles, and fonts. ```typescript interface EmailLayoutProps { backdropColor?: string; // Color of area outside email canvas canvasColor?: string; // Main background color of email textColor?: string; // Default text color (inherited by all blocks) fontFamily?: FontFamily; // Default font (inherited by all blocks) borderColor?: string; // Border around canvas borderRadius?: number; // Rounded corners on canvas childrenIds?: string[]; // IDs of blocks to render } ``` -------------------------------- ### Button Component Configuration Source: https://github.com/usewaypoint/email-builder-js/blob/main/_autodocs/api-reference/blocks.md Configure a Button component with custom styles, text, URL, and appearance. Supports various sizes, colors, and shapes. Useful for calls to action in emails. ```typescript function Button(props: ButtonProps): JSX.Element interface ButtonProps { style?: { backgroundColor?: ColorString | null; fontSize?: number | null; fontFamily?: FontFamily; fontWeight?: 'bold' | 'normal' | null; textAlign?: 'left' | 'center' | 'right' | null; padding?: PaddingObject; } | null; props?: { buttonBackgroundColor?: ColorString | null; buttonStyle?: 'rectangle' | 'pill' | 'rounded' | null; buttonTextColor?: ColorString | null; fullWidth?: boolean | null; size?: 'x-small' | 'small' | 'medium' | 'large' | null; text?: string | null; url?: string | null; } | null; } ``` ```typescript