---
title: Serialize Portable Text to Vue
description: Render Portable Text in Vue 3 and Nuxt using @portabletext/vue
tags: [portable-text, vue, nuxt, serialization, rendering]
---
# Serialize Portable Text to Vue
Use `@portabletext/vue` to render PT in Vue 3 / Nuxt applications.
```bash
npm install @portabletext/vue
```
## Basic Usage
```vue
```
## Custom Components
Vue components can be defined as render functions, SFCs, or JSX.
### Render Function Style (Concise)
```ts
import {h} from 'vue'
import type {PortableTextVueComponents} from '@portabletext/vue'
const components: PortableTextVueComponents = {
types: {
image: ({value}) => h('img', {src: urlFor(value).width(800).url(), alt: value.alt || ''}),
code: ({value}) => h('pre', {'data-language': value.language}, h('code', value.code)),
},
marks: {
link: ({value}, {slots}) => {
const rel = !value?.href?.startsWith('/') ? 'noreferrer noopener' : undefined
return h('a', {href: value?.href, rel}, slots.default?.())
},
highlight: (_, {slots}) => h('span', {class: 'bg-yellow-200'}, slots.default?.()),
},
block: {
h1: (_, {slots}) => h('h1', {class: 'text-4xl font-bold'}, slots.default?.()),
h2: (_, {slots}) => h('h2', {class: 'text-3xl font-semibold'}, slots.default?.()),
blockquote: (_, {slots}) => h('blockquote', {class: 'border-l-4 pl-4 italic'}, slots.default?.()),
},
list: {
bullet: (_, {slots}) => h('ul', {class: 'list-disc ml-6'}, slots.default?.()),
number: (_, {slots}) => h('ol', {class: 'list-decimal ml-6'}, slots.default?.()),
},
}
```
### SFC Style (For Complex Components)
```vue
{{ value.caption }}
```
Then register:
```ts
import ImageBlock from './ImageBlock.vue'
const components = {
types: {
image: ImageBlock,
},
}
```
## Props Pattern
Custom components receive:
| Prop | Description |
|------|-------------|
| `value` | The block/mark data |
| `index` | Position in parent array |
| `isInline` | Whether this is an inline element |
| `renderNode` | Internal renderer (rarely needed) |
Children are passed via **slots** (`slots.default?.()`), not props.
## Plain Text Extraction
```ts
import {toPlainText} from '@portabletext/vue'
const text = toPlainText(blocks)
```
## Reference
- [@portabletext/vue](https://github.com/portabletext/vue-portabletext)
- [Sanity + Nuxt guide](https://www.sanity.io/guides/sanity-nuxt)