--- title: Serialize Portable Text to HTML description: Convert Portable Text to HTML strings server-side using @portabletext/to-html tags: [portable-text, html, server-side, serialization, email] --- # Serialize Portable Text to HTML Use `@portabletext/to-html` for server-side HTML string generation — useful for RSS feeds, emails, static rendering, or any non-framework context. ```bash npm install @portabletext/to-html ``` ## Basic Usage ```ts import {toHTML} from '@portabletext/to-html' const html = toHTML(portableTextBlocks, {components}) ``` ## ⚠️ Security: Escape HTML Unlike framework renderers, `toHTML` returns raw strings. **You must sanitize output.** Use `htm` + `vhtml` for safe templating, or the built-in `escapeHTML` utility: ```ts import {toHTML, escapeHTML, uriLooksSafe} from '@portabletext/to-html' import htm from 'htm' import vhtml from 'vhtml' const h = htm.bind(vhtml) ``` ## Custom Components Components are functions returning HTML strings: ```ts const components = { types: { image: ({value}) => { return `
${escapeHTML(value.alt || '')} ${value.caption ? `
${escapeHTML(value.caption)}
` : ''}
` }, code: ({value}) => { return `
${escapeHTML(value.code)}
` }, }, marks: { link: ({children, value}) => { const href = value?.href || '' if (!uriLooksSafe(href)) return children const rel = href.startsWith('/') ? '' : ' rel="noreferrer noopener"' return `${children}` }, strong: ({children}) => `${children}`, em: ({children}) => `${children}`, highlight: ({children}) => `${children}`, }, block: { h1: ({children}) => `

${children}

`, h2: ({children}) => `

${children}

`, blockquote: ({children}) => `
${children}
`, normal: ({children}) => `

${children}

`, }, list: { bullet: ({children}) => ``, number: ({children}) => `
    ${children}
`, }, listItem: { bullet: ({children}) => `
  • ${children}
  • `, }, } ``` ## With htm/vhtml (Auto-Escaped) Using `htm` + `vhtml` auto-escapes attribute values, preventing XSS from user content that could break out of attributes in raw template literals: ```ts const components = { types: { image: ({value}) => h`${value.alt`, }, marks: { link: ({children, value}) => { if (!uriLooksSafe(value?.href || '')) return children return h`${children}` }, }, } ``` ## Use Cases | Use Case | Why toHTML | |----------|-----------| | RSS/Atom feeds | Need raw HTML string | | Email templates | No framework runtime | | Static site generation | Pre-render at build time | | API responses | Return HTML from endpoints | | PDF generation | Feed HTML to PDF libraries | ## Reference - [@portabletext/to-html](https://github.com/portabletext/to-html)