In this guide, you’ll learn how to configure the prebuilt editor’s export button to produce PDF output. In the new configuration architecture, the export action is routed through onExport, and your callback owns the full flow: export the buffer, write it to disk, then decide whether to share or persist the file.
What You’ll Learn#
- Switch the prebuilt editor’s export to PDF via
onExport. - Implement your own save/share flow for the exported file.
- Add export options (DPI, high-compat, underlayer) for design scenes.
- Keep MP4 export for video scenes while using PDF for design scenes.
When to Use It#
- You want editor UI out of the box, with export customized to PDF.
- You want to control how the exported file is written, stored, or shared.
- You need optional export tweaks but still want to keep the prebuilt editor UI.
Export Control#
The prebuilt editors have an export control in the navigation bar. In the new architecture, tapping it invokes EditorConfiguration.onExport. The editor does not provide a built-in share-sheet fallback, so your callback needs to export the buffer, write it to a file, and hand it off to your app’s save/share flow.

If your export to PDF is straightforward, you can override onExport and keep the logic focused on the export itself.
onExport = { val engine = editorContext.engine state = state.copy(isLoading = true) runCatching { val buffer = engine.block.export( block = requireNotNull(engine.scene.get()), mimeType = MimeType.PDF, onPreExport = { scene.getPages().forEach { page -> block.setScopeEnabled(page, key = "layer/visibility", enabled = true) block.setVisible(page, visible = true) } }, ) writeToTempFile(buffer, MimeType.PDF) }.onSuccess { file -> state = state.copy(isLoading = false) // Do something with the file }.onFailure { state = state.copy(isLoading = false, error = it) }}The preceding code:
- Exports the currently loaded scene as a PDF.
- Writes the PDF buffer to a temporary file that your app can then share or persist.
- Updates local UI state while the export is running and when it fails.
private suspend fun writeToTempFile( byteBuffer: ByteBuffer, mimeType: MimeType = MimeType.PDF,): File = withContext(Dispatchers.IO) { val extension = mimeType.key.split("/").last() File .createTempFile(UUID.randomUUID().toString(), ".$extension") .apply { outputStream().channel.write(byteBuffer) }}Adding Options to Export#
For more complex configurations, you can use ExportOptions to customize the PDF output. If the same UI can open both static and timeline-based scenes, branch on whether the current page supports playback time and keep MP4 export for pages that behave like video timelines.
Editor( license = null, // pass null or empty for evaluation mode with watermark configuration = { EditorConfiguration.remember { onExport = { val engine = editorContext.engine val page = engine.scene.getCurrentPage() ?: engine.scene.getPages()[0] if (engine.block.supportsPlaybackTime(page)) { val buffer = engine.block.exportVideo( block = page, timeOffset = 0.0, duration = engine.block.getDuration(page), mimeType = MimeType.MP4, progressCallback = {}, ) val file = writeToTempFile(buffer, MimeType.MP4) // Share or persist the video file here. } else { val options = ExportOptions( exportPdfWithHighCompatibility = true, exportPdfWithUnderlayer = true, underlayerSpotColorName = "White", underlayerOffset = -2.0f, ) val buffer = engine.block.export( block = requireNotNull(engine.scene.get()), mimeType = MimeType.PDF, options = options, ) val file = writeToTempFile(buffer, MimeType.PDF) // Share or persist the PDF file here. } } } },)The preceding code creates an ExportOptions object and passes it to the PDF export function. You can configure additional options like underlayer generation and DPI settings.
Once the file has been written to disk, hand it off to your app’s share or save flow. For video scenes, keep using exportVideo.
Export Options#
The ExportOptions class provides these parameters for PDF customization:
val options = ExportOptions( exportPdfWithHighCompatibility = true, // Flatten complex elements exportPdfWithUnderlayer = true, // Generate print underlayer underlayerSpotColorName = "White", // Spot color for underlayer ink underlayerOffset = -2.0f, // Offset in design units)Available options:
exportPdfWithHighCompatibility: Flatten PDF for better compatibility with older viewers.exportPdfWithUnderlayer: Generate an underlayer shape for specialized printing (fabric, glass).underlayerSpotColorName: Specify the spot color name for the underlayer ink.underlayerOffset: Adjust underlayer size with positive (larger) or negative (smaller) offset.
Troubleshooting#
❌ Export still uses PNG/MP4 logic:
- The SDK no longer has a built-in PNG/MP4 export fallback. If you still see those formats, they are coming from your own
onExportimplementation. - Ensure non-timeline pages call
engine.block.export(..., mimeType = MimeType.PDF). - If your editor can open timeline-based pages, verify that
exportVideo(...)only runs for pages that actually support playback time. - If you removed your custom
onExportcallback entirely, note that the default implementation only logs a warning and does not export anything.
❌ PDF looks soft:
- Check the
"scene/dpi"property of the scene and increase it if necessary. - Ensure placed images have enough pixels to cover the frame.
❌ Underlayer absent in output:
- Verify the spot color name is correct and matches what the printer expects.
- Ensure
exportPdfWithUnderlayer = trueis set inExportOptions. - Do not flatten the PDF or the underlayer will be lost.
❌ Video scene needs a different flow:
- This is expected. Check whether the current page supports playback time and call
exportVideofor timeline-based pages instead ofexport.
Next Steps#
Now that you know how to configure the editor to export to PDF, here are some topics to explore:
- Spot Colors – use spot colors for specialized printing.
- Asset Sources & Upload – bring user images/videos in, then export as PDF.