Node API

renderToStream

Renders a PDF document and returns a readable stream, ideal for piping directly to HTTP responses.

Signature

ts
function renderToStream(
  element: Component,
  props?: Record<string, unknown>
): Promise<ReadableStream>

Usage

ts
import { renderToStream } from '@vuepdf/renderer'
import MyDocument from './MyDocument.vue'

app.get('/pdf', async (req, res) => {
  const stream = await renderToStream(MyDocument)

  res.setHeader('Content-Type', 'application/pdf')
  stream.pipe(res)
})

Nuxt Server Route

In a Nuxt app, a route under server/api/ can stream the PDF straight to the client with h3's sendStream:

server/api/report.get.ts
// server/api/report.get.ts
import { renderToStream } from '@vuepdf/renderer'
import ReportDocument from '../../components/pdf/ReportDocument.vue'

export default defineEventHandler(async (event) => {
  const { title = 'Report' } = getQuery(event) as { title?: string }

  setHeader(event, 'content-type', 'application/pdf')
  setHeader(event, 'content-disposition', 'inline; filename="report.pdf"')

  return sendStream(event, await renderToStream(ReportDocument, { title }))
})
components/pdf/ReportDocument.vue
<!-- components/pdf/ReportDocument.vue -->
<script setup lang="ts">
import { Document, Page, Text } from '@vuepdf/renderer/components'

defineProps<{ title: string }>()
</script>

<template>
  <Document :title="title">
    <Page size="A4" :style="{ padding: 48, fontSize: 12 }">
      <Text :style="{ fontSize: 24, marginBottom: 12 }">
        {{ title }}
      </Text>
      <Text>
        Generated on the server with renderToStream.
      </Text>
    </Page>
  </Document>
</template>
vue
<template>
  <a href="/api/report?title=Quarterly%20Report" target="_blank">
    Open the PDF
  </a>
</template>

Keep PDF component imports inside the document component. Nitro can import the document SFC from the server route, and the document can import primitives from @vuepdf/renderer/components.

For generated trees without Vue templates, @vuepdf/renderer/primitives remains available.

Importing a .vue document from a server route requires the @vuepdf/nuxt module. Nitro bundles server/ without Vue support, so the module registers a Vue SFC plugin for it; without that the build fails with rollup-plugin-inject: failed to parse YourDocument.vue. Outside Nuxt — plain Node or Express — either precompile the SFC in your own build, or build the document from @vuepdf/renderer/primitives instead.
Need the same document in the browser? Render it client-side with usePDF or PDFDownloadLink.

Related

Use renderToBuffer when you need the bytes in memory rather than a stream — for caching, uploading, or setting an explicit content-length.