---
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 `
${value.caption ? `
${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}`, normal: ({children}) => `
${children}
`, }, list: { bullet: ({children}) => `