Exports
Every canvas can leave the platform. PNG for sharing in a deck or a chat thread. PDF for paper or attaching to an email. Save to Brain for keeping the artefact alongside the user's other memories where future skills can read it. The exporter renders the same JSX the chat surface renders, then serialises it through the right pipeline.
Overview
- Picker component
src/components/canvas/CanvasExportPicker.tsx- Render API
POST /api/canvas/export- Targets
- PNG, PDF, Save to Brain
- Render engine
- Headless Chromium via Playwright in the sandbox
- PNG DPR
- 2 by default (retina sharp)
- Brain ingest
- PDF → POST /api/brain/files
Exports use the same renderer the chat surface uses. The JSX that draws the canvas inline is the JSX that gets rasterised when you press export. There is no parallel rendering path that could drift; if the canvas looks right inline, it exports right.
Three targets
One picker, three destinations.
| Target | What you get | Where it goes |
|---|---|---|
| PNG | A 2x-DPR raster image of the canvas at its native rendered size | Downloaded to the user's machine |
| A single-page PDF with the canvas rendered at full width on letter paper | Downloaded to the user's machine | |
| Save to Brain | Same PDF, pushed straight into the user's brain files surface | Becomes searchable memory after chunking and embedding |
PNG export
The picker calls the export endpoint with target=png. The endpoint renders into an offscreen container in the sandbox and takes a Playwright screenshot.
document.fonts.ready before firing so custom fonts have actually loaded. Without that wait the screenshot occasionally captures a fallback font.PDF export
Same render, different serialisation. PDF goes through Playwright's print API.
Backgrounds are forced on because canvases use surface colours to communicate (status pills, table zebra stripes). The default Letter format with half-inch margins fits a single canvas comfortably without forced shrinking; the renderer chooses the layout that fits the page.
Save to Brain
The PDF gets pushed into the user's brain files so future skills can ground on it.
- 01Render PDFSame path as the PDF target. The buffer never lands on disk; it is streamed directly into the upload step.
- 02Upload to /api/brain/filesThe endpoint accepts the buffer plus a generated filename (
canvas-<skill_id>-<timestamp>.pdf) and inserts a brain file row with status processing. - 03Async chunkerThe chunker parses the PDF, splits it into passages, embeds each one, and writes rows into file_embeddings. The file moves to status ready.
- 04SearchableThe canvas content is now retrievable through
brain_search_files. Skills that ground on the user's documents will find it.
The picker UI
A small dropdown on the canvas toolbar.
Behind the scenes
The export endpoint runs inside the user's isolated per-conversation sandbox so heavy Playwright work does not block the containerized cloud runtime that serves chat.
Headless Chromium plus Playwright is heavyweight to spin up. Doing it inside the same containerized cloud runtime that serves chat requests would steal memory from interactive turns. Instead the export endpoint pushes the render job into the user's sandbox where Playwright is already installed (the sandbox has all the system libraries pre-baked from the workspace template) and the result streams back to the caller.
If the sandbox is not warm at export time, the endpoint spawns one for the render and tears it down afterwards. The first export of a fresh session pays the warm-boot cost; subsequent exports are fast.
File map
Glossary
- Export
- The act of taking a canvas out of the chat surface, either by downloading it or by saving it into the user's Brain.
- Target
- Which of the three destinations an export goes to: PNG, PDF, Save to Brain.
- DPR
- Device pixel ratio. PNG exports render at 2x so the result is sharp on retina displays.
- Save to Brain
- An export that pushes the rendered PDF into the user's brain files where the chunker makes it searchable.
- Headless Chromium
- The browser engine the exporter uses to render the canvas JSX. Driven by Playwright inside the user's sandbox.