PDF Preview Guide
This guide covers how to display PDF documents inline using `pdf-preview` code blocks.
This guide covers how to display PDF documents inline using pdf-preview code blocks.
Overview
The pdf-preview block renders PDF files inline in chat messages — showing the first page with an expand button for full multi-page navigation in a fullscreen overlay.
| Format | Best For | Rendering |
|---|---|---|
pdf-preview block | PDF documents, reports, invoices | First page inline, full navigation in fullscreen |
html-preview block | Emails, newsletters, styled HTML | Sandboxed iframe with full CSS |
datatable/spreadsheet | Structured data, tables | Interactive sortable/filterable tables |
Key principle: Unlike html-preview which needs transform_data to extract HTML, PDFs are already files on disk. Just reference the file path directly — no extraction step needed.
When to Use
Use pdf-preview when:
- Tool results reference a PDF file — Read tool, file downloads, API responses with PDF paths
- Generated reports — Scripts or tools that produce PDF output
- Downloaded documents — PDFs fetched from APIs or saved from web
- User asks to view a PDF — Any PDF file the user mentions or references
Do NOT use pdf-preview when:
- Content is structured data — use
datatableorspreadsheetinstead - Content is HTML — use
html-previewinstead - The PDF is a code/text file — just read it and present as markdown
- The user wants to extract text from the PDF — use the Read tool's PDF support instead
Basic Usage
Single Item
```pdf-preview
{
"src": "/absolute/path/to/file.pdf",
"title": "Q4 Financial Report"
}
```Multiple Items (Tabs)
When you have multiple related PDFs (e.g., quarterly reports, contract versions), use the items array. A tab bar appears below the header for switching between items.
```pdf-preview
{
"title": "Quarterly Reports",
"items": [
{ "src": "/path/to/q1-report.pdf", "label": "Q1" },
{ "src": "/path/to/q2-report.pdf", "label": "Q2" },
{ "src": "/path/to/q3-report.pdf", "label": "Q3" }
]
}
```Content loads lazily on tab switch and is cached once loaded.
Config Fields
| Field | Required | Type | Description |
|---|---|---|---|
src | Yes* | string | Absolute path to the PDF file on disk (single item mode) |
title | No | string | Display title shown in the header bar (defaults to "PDF Preview") |
items | Yes* | array | Array of items with src and optional label (multi-item mode) |
items[].src | Yes | string | Absolute path to the PDF file |
items[].label | No | string | Tab label (defaults to "Item 1", "Item 2", etc.) |
*Either src (single) or items (multiple) is required. If both are present, items takes precedence.
Important: The src path must be an absolute path. Use the exact path from tool results or construct one using known directory paths.
Common Patterns
After Using the Read Tool on a PDF
When the Read tool reads a PDF, the file already exists on disk. Reference it directly:
```pdf-preview
{
"src": "/Users/john/Documents/report.pdf",
"title": "Annual Report 2025"
}
```PDF from API Download
When a tool downloads a PDF (e.g., from an API response that returns binary data):
- The file is typically saved to the session downloads folder
- Reference the saved path in the
pdf-previewblock
```pdf-preview
{
"src": "/absolute/path/to/downloaded/invoice.pdf",
"title": "Invoice #12345"
}
```PDF Generated by a Script
When running a Python script that generates a PDF (e.g., with reportlab, fpdf2, or weasyprint):
# Example: generate PDF with fpdf2
from fpdf import FPDF
import sys
pdf = FPDF()
pdf.add_page()
pdf.set_font('Helvetica', size=16)
pdf.cell(text='Hello World')
pdf.output(sys.argv[-1])Call via transform_data, then reference the output:
```pdf-preview
{
"src": "/absolute/path/from/transform_data/report.pdf",
"title": "Generated Report"
}
```PDF from User's Filesystem
When the user references a PDF they have locally:
```pdf-preview
{
"src": "/Users/john/Downloads/contract.pdf",
"title": "Service Agreement"
}
```Rendering Behavior
Inline Preview
- Shows first page only at max-height 400px with bottom fade gradient
- White background — standard for PDF documents
- Expand button (top-right corner, visible on hover) opens fullscreen view
- Header bar shows FileText icon and title
- No pagination controls inline — use fullscreen for multi-page navigation
Fullscreen Overlay
- Full page-by-page navigation with prev/next buttons
- Page counter showing "Page X / Y"
- Copy path button copies the file path to clipboard
- "PDF" badge in header identifies the content type
- Text selection and annotation layers enabled for interactivity
Performance Notes
- PDFs are loaded as binary data (
Uint8Array) via IPC — efficient even for large files - The pdf.js worker handles decoding and rendering in a background thread
- Inline preview only renders page 1 — remaining pages load on-demand in fullscreen
- The file object is memoized to prevent unnecessary re-renders
Integration with Read Tool
The Read tool already supports reading PDFs with the pages parameter. Use pdf-preview for visual rendering and Read for text extraction:
| Goal | Tool |
|---|---|
| See the PDF visually | pdf-preview code block |
| Extract text content | Read tool with pages parameter |
| Both | Use Read to extract text, then show pdf-preview for visual reference |
Decision Tree
Does the user want to SEE the document?
→ YES: Use pdf-preview (visual fidelity matters)
→ NO: Extract text with Read tool and present as markdown
Is the content already a PDF file on disk?
→ YES: Use pdf-preview with direct file path
→ NO: Is it HTML? → Use html-preview
Is it data? → Use datatable/spreadsheet
Is it binary from an API? → Save to file first, then pdf-previewTroubleshooting
"Loading..." shown indefinitely
- The
"src"path must be an absolute path — not relative - Verify the file exists at the specified path
- Check that the file is actually a PDF (not renamed HTML, etc.)
Blank/white preview
- The PDF file may be empty or corrupted
- Some encrypted PDFs require a password — pdf.js cannot render these
- Try opening the file with a system PDF viewer to verify it's valid
First page looks cut off
- The inline preview has a max-height of 400px — this is by design
- Click the expand button (top-right) for full-page rendering
- In fullscreen, the page renders at full size with scrolling
"Failed to render PDF" error
- The file may not be a valid PDF
- Very large PDFs (100MB+) may fail to load — consider extracting specific pages first
- Scanned PDFs render as images — this is expected behavior
Fullscreen overlay shows different content
- The overlay loads the PDF independently from the file path
- If the file was modified between inline load and fullscreen open, content may differ
Text not selectable in inline preview
- Text selection is intentionally disabled in the inline preview (renders without text layer for performance)
- Open fullscreen view for text selection support — the text layer is enabled there
HTML Preview Guide
This guide covers how to render rich HTML content inline using `html-preview` code blocks, and how to use `transform_data` to prepare HTML files from various so
Data Tables Guide
This guide covers how to present structured data using datatable and spreadsheet blocks, and how to use the `transform_data` tool for large datasets.