Build reusable document components
Organize repeated PDF sections without creating a second component system.
PDF components are ordinary local Vue components whose rendered roots are Nuxt PDF primitives. Extract a component when it owns a meaningful document section or repeats in more than one place.
Keep ownership visible
Put document-specific components next to their document family:
pdfs/
├── invoice.vue
└── components/
└── invoice/
├── InvoiceAddress.vue
├── InvoiceLine.vue
└── columns.tsMove a component to pdfs/components/ only when several templates use it. This
keeps invoice-specific decisions out of a generic component API.
Pass typed document data
<script setup lang="ts">
defineProps<{
label: string
lines: string[]
}>()
</script>
<template>
<PdfView>
<PdfText :style="{ fontSize: 8, marginBottom: 4 }">
{{ label }}
</PdfText>
<PdfText v-for="line in lines" :key="line">
{{ line }}
</PdfText>
</PdfView>
</template>Import it directly in the template. Use keyed v-for, slots, and v-if as you
would in another Vue component. Do not pass DOM attributes such as class or
aria-*; the PDF tree has no DOM.
Share table geometry
Put widths used by both a header and row in one TypeScript module:
export const invoiceColumns = {
description: '58%',
quantity: '14%',
price: '14%',
total: '14%',
} as constA table is a column of rows. Give the header and every row the same
flexDirection: 'row' and column widths. The header and body then cannot drift
apart.
The production recipes show address blocks, shared columns, totals, continuation headers, and table-of-contents patterns.