
Security News
New React Server Components Vulnerabilities: DoS and Source Code Exposure
New DoS and source code exposure bugs in React Server Components and Next.js: whatβs affected and how to update safely.
typst-pagemaker
Advanced tools
Structured document-to-page layout system for Typst with explicit positioning and professional typography
Please note: This project is in no way affiliated with or related to the old Aldus PageMaker program from the 90s.
A dual-export document layout system that transforms org-mode files into professional PDFs and web-optimized HTML.
PDF Export: Precise grid-based positioning with Typst's powerful typesetting engine for print-ready documents.
HTML Export: Grid-faithful web rendering with CSS Grid layouts that mirror PDF positioning, optimized for web viewing.

PDF Mode (Precision Layout):
Unlike traditional document systems that rely on automatic text flow and built-in spacing, pagemaker takes a fundamentally different approach:
This approach is ideal for creating presentations, posters, reports, and any document where you need pixel-perfect control over layout and positioning.
HTML Export (Web Viewing):
For web-focused output, HTML export provides maximum PDF fidelity in the browser:
HTML export is ideal for creating web presentations, documentation, and any content that needs to match PDF layout while being viewable in browsers.
Media Embedding Updates: All media types (images, PDFs, SVGs) now support unified fit modes with consistent behavior.
Current behavior (all media types):
contain, cover, stretch:ALIGN:, :VALIGN:) control positioning and visible regionMigration steps:
:PDF: and :SVG: properties are deprecatedβuse [[file:...]] links (recommended) or :SRC: property[[file:...]] link syntax:PDF_ALIGN: property was removedβuse standard :ALIGN: / :VALIGN:See the Media Embedding section for comprehensive documentation.
Two Export Formats:
Common Features:
When to Use Each Format:
| Use Case | PDF Export | HTML Export |
|---|---|---|
| Print documents | β Best choice | β Not suitable |
| Presentations (offline) | β Precise control | β οΈ Web only |
| Web presentations | β οΈ Static PDF | β Interactive, responsive |
| Documentation | β Professional | β Modern, searchable |
| Marketing materials | β Print-ready | β Web-optimized |
| Precise positioning required | β Pixel-perfect | β Grid-faithful CSS |
| Quick prototyping | β οΈ Requires positioning | β Same layout as PDF |
| Custom styling needed | β οΈ Typst syntax | β Standard CSS |
:JUSTIFY: for header/subheader/body elements:PADDING: on all element types with CSS-like TRBL shorthand:ALIGN: / :VALIGN: for precise positioning within frames; :FLOW: for layout hints| Element Type | Description | Properties |
|---|---|---|
header | Main headings | Font: Inter Bold, 24pt |
subheader | Section headings | Font: Inter SemiBold, 18pt |
body | Regular text | Font: Inter Regular |
figure | Images/media with captions | Supports all fit modes, captions, page selection |
pdf | Vector PDF embedding | Contain-only scaling, captions, page selection |
svg | SVG vector graphics | Contain-only scaling, intrinsic size detection |
rectangle | Colored overlays | Color, alpha, stroke, radius |
toc | Table of contents | Auto-lists slide titles |
Media Elements: See the Media Embedding section below for comprehensive documentation on fit modes, alignment, captions, and sizing behavior.
# Install from PyPI
pip install typst-pagemaker
# Verify installation
pagemaker --help
typst --version # Ensure Typst is also installed
Essential Dependencies:
--sanitize-pdfs functionalityOptional Dependencies:
Install platform-specific dependencies:
# macOS (via Homebrew)
brew install typst mupdf qpdf ghostscript
# Ubuntu/Debian
sudo apt update && sudo apt install typst-cli mupdf-tools qpdf ghostscript
# Arch Linux
sudo pacman -S typst mupdf-tools qpdf ghostscript
# Windows (via winget or chocolatey)
winget install --id Typst.Typst
# For MuPDF, download from: https://mupdf.com/releases/index.html
# Clone the repository for development
git clone https://github.com/sanderboer/typst-pagemaker.git
cd typst-pagemaker
# Install in editable mode
pip install -e .
pagemaker --help
Continuously rebuild output when the source Org file or referenced assets change.
PDF/Typst Mode:
# Rebuild typst on change
pagemaker watch examples/sample.org --export-dir export
# Build PDF on each change, keep intermediate .typ
pagemaker watch examples/sample.org --pdf --no-clean --export-dir export
# Single build (no loop) - useful for tests
pagemaker watch examples/sample.org --once --export-dir export
HTML Export:
# Auto-rebuild HTML on changes (inline CSS/JS)
pagemaker watch examples/sample.org --html-mode
# Auto-rebuild with separate CSS/JS files (recommended for development)
pagemaker watch examples/sample.org --html-mode --separate-assets
# Custom export directory
pagemaker watch document.org --html-mode --export-dir web/
Watch mode monitors your org file and all referenced assets (images, SVGs, PDFs via [[file:...]] links). When any file changes, output is automatically regenerated.
Options:
--interval <seconds>: Polling interval (default 1.0)--once: Perform exactly one build then exit--export-dir <path>: Custom export directory (default: export/)PDF/Typst Mode Options:
--pdf: Also compile PDF each rebuild--pdf-output <file>: Custom PDF filename--typst-bin <path>: Path to typst binary--no-clean: Keep the intermediate .typ after PDF build--update-html <path>: Update existing HTML file's page count placeholder--sanitize-pdfs: Attempt to sanitize PDFs; if Typst compile still fails, auto-fallback to SVG or PNG for the requested pageHTML Export Options:
--html-mode: Generate HTML export instead of PDF/Typst (watch mode)--separate-assets: Generate separate CSS/JS files (easier to customize)# Build Typst from Org (org -> typst)
pagemaker build examples/sample.org -o deck.typ
# Build and produce PDF (cleans .typ by default)
pagemaker pdf examples/sample.org --pdf-output deck.pdf
# Build with PDF sanitize + fallback (qpdf/mutool/gs optional)
pagemaker pdf examples/sample.org --sanitize-pdfs --pdf-output deck.pdf
# Generate HTML Export (grid-faithful web rendering)
pagemaker html examples/sample.org
pagemaker html examples/sample.org --separate-assets # Easier to customize
# Emit IR JSON to stdout
pagemaker ir examples/sample.org > ir.json
# Validate IR (non-zero exit on error)
pagemaker validate examples/sample.org
| Command | Purpose | Output |
|---|---|---|
watch | Auto-rebuild on changes | PDF or HTML export |
html | Generate web export | HTML with CSS/JS |
pdf | Build PDF document | PDF file |
build | Generate Typst code | .typ file |
snapshot | Package document with assets | Self-contained directory |
ir | Export intermediate representation | JSON to stdout |
validate | Check document validity | Exit code (0=valid) |
fonts list | Show available fonts | Font list |
fonts download | Download Google Fonts | Font files |
fonts analyze | Show document font usage | Usage report |
Most Common Workflows:
# Development: Live preview while editing
pagemaker watch document.org --html-mode --separate-assets # Web (HTML)
pagemaker watch document.org --pdf # Print (PDF)
# Production: Final output
pagemaker html document.org --separate-assets # Web
pagemaker pdf document.org --pdf-output final.pdf # Print
# Package: Create self-contained snapshot
pagemaker snapshot document.org --output-dir ./snapshots # Complete package
Create self-contained packages of your documents, similar to InDesign's "Package" feature. Perfect for archiving, sharing, or moving projects between systems.
What's Included:
Basic Usage:
# Create snapshot with PDF (default behavior)
pagemaker snapshot document.org --output-dir ./snapshots
# Create snapshot without PDF (faster)
pagemaker snapshot document.org --output-dir ./snapshots --no-build-pdf
# With custom Typst binary
pagemaker snapshot document.org --typst-bin /usr/local/bin/typst
Output Structure:
251128-document_snapshot/
βββ document.org # Updated with ./assets/ paths
βββ document.pdf # Compiled PDF (if built)
βββ assets/ # All media files
β βββ photo1.jpg
β βββ diagram.svg
β βββ ...
βββ fonts/ # All referenced fonts
β βββ Inter-Regular.woff2
β βββ Inter-Bold.woff2
β βββ ...
βββ README.txt # Package metadata
Key Features:
./assets/...Use Cases:
Enhance PDF output with OutputIntent injection for professional print workflows and PDF/A compliance. This feature adds ICC color profiles to PDFs, improving color accuracy and meeting archival standards.
Requirements:
Basic Usage:
# Inject sRGB OutputIntent (auto-discovers system sRGB profile)
pagemaker pdf examples/sample.org --inject-output-intent-srgb --pdf-output document.pdf
# Use custom ICC profile
pagemaker pdf examples/sample.org --icc-profile /path/to/profile.icc --pdf-output document.pdf
# Combine with PDF presets for print production
pagemaker pdf examples/sample.org --inject-output-intent-srgb --pdf-preset prepress --pdf-output document.pdf
# Works in watch mode too
pagemaker watch examples/sample.org --pdf --inject-output-intent-srgb --export-dir export
Available Options:
--inject-output-intent-srgb: Automatically discovers and injects system sRGB ICC profile--icc-profile <path>: Inject custom ICC profile from specified file path--pdf-preset <preset>: Apply PDF optimization preset (screen, printer, prepress)PDF Presets:
screen: Optimized for digital display and web viewingprinter: Balanced settings for general printingprepress: High-quality prepress settings for professional printingGraceful Fallback:
Use Cases:
Technical Details:
Manual Typst compile (if you only produced .typ):
typst compile --root . --font-path assets/fonts --font-path assets/fonts/static export/deck.typ export/deck.pdf
Or use the Makefile targets:
make debug-overlay # Build debug example
When exporting into an export/ directory, any relative asset references in the Org file like:
[[file:assets/diagram.png]]
:PDF: assets/spec.pdf
:SVG: assets/graphics/logo.svg
are automatically rewritten so the generated deck.typ can reside in export/ while still finding the assets in the project root. You can also use absolute paths if preferred.
Media elements (figure, pdf, svg) accept source paths via [[file:...]] links (preferred, native org-mode) or the :SRC: property. Precedence rules:
[[file:...]] link exists in content, it is used (native org-mode syntax - recommended):SRC: property is present and non-empty, it is used:PDF: for pdf, :SVG: for svg - deprecated):SRC: and a legacy key are present, the legacy key is ignored (deprecation warning emitted)Recommended syntax (native org-mode):
** Vector Logo
:PROPERTIES:
:TYPE: svg
:END:
[[file:assets/graphics/logo.svg]]
** Plan Page 2
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:END:
[[file:assets/spec.pdf]]
** Cover Image
:PROPERTIES:
:TYPE: figure
:FIT: cover
:END:
[[file:assets/test-images/forest.jpg]]
Alternative syntax (property-based):
** Vector Logo
:PROPERTIES:
:TYPE: svg
:SRC: assets/graphics/logo.svg
:END:
Both syntaxes work for all media types. Use [[file:...]] for consistency with org-mode conventions.
All path rewriting is centralized in AssetPathResolver (src/pagemaker/utils/assets_paths.py). It converts element figure/pdf/svg src values into paths relative to the chosen export (--export-dir) so the .typ file can move independently of your assets.
Precedence (non-strict mode):
/abs/path, https://...) are passed through unchanged.pagemaker from).pyproject.toml or .git).deck.typ).assets/, the resolver also tries <project_root>/examples/<src>.Strict mode difference: In strict mode (unused by CLI today) missing relative paths are left unchanged (they will likely cause a later failure) instead of being rewritten via best-effort mapping.
Caching: Resolutions are memoized per original src string for the lifetime of the resolver instance (improves large document builds).
Examples Fallback Use Case:
If you reference an asset that only exists under examples/assets/... (e.g. [[file:assets/test-images/forest.jpg]]) and you run the CLI from the project root, the resolver will rewrite the path to a relative traversal pointing into examples/assets/.... This lets example Org files stay portable without copying assets into the top-level assets/ folder.
Debugging Path Decisions:
Set environment variable PAGEMAKER_DEBUG_ASSET_PATHS=1 when running any CLI command to log each asset rewrite:
PAGEMAKER_DEBUG_ASSET_PATHS=1 pagemaker build examples/sample.org --export-dir export
Log lines look like:
[asset-path-debug] src='assets/test-images/forest.jpg' -> '../examples/assets/test-images/forest.jpg' (resolved:/absolute/path/to/examples/assets/test-images/forest.jpg)
Reason codes:
resolved:<absolute>: Chosen candidate path existed.unchanged-strict-or-absent: Strict mode left path unchanged or no mapping was possible.Absolute / Protocol Short-Circuit:
Values beginning with / or containing a protocol scheme (e.g. https://, s3://) bypass all rewriting and remain exactly as specified.
Best Practices:
assets/... paths for portability (works with examples fallback).Future Enhancements:
--strict-assets) already exists on the validate subcommand for treating missing figure/pdf assets as errors (operates after rewriting).Dynamic helpers available in text:
#page_no / #page_total for page counters (no parentheses; Typst context-based).#date_iso (YYYY-MM-DD), #date_yy_mm_dd (YY.MM.DD), #date_dd_mm_yy (DD.MM.YY)#+DATE_OVERRIDE: YYYY-MM-DD (or #+DATE:) in the Org meta header.TOC element:
toc element to list slide titles automatically.** Table of Contents
:PROPERTIES:
:TYPE: toc
:AREA: A1,L8
:PADDING: 4,6
:END:
Text: use :JUSTIFY: to enable full justification and :PADDING: to inset content in millimeters.
(place this snippet in the examples folder in order for pagemaker to find the fonts and images that are already bundled in the examples/asset folder)

#+TITLE: My Presentation
#+PAGESIZE: A4
#+ORIENTATION: landscape
#+GRID: 12x8
#+GRID_DEBUG: false
#+STYLE_WHITE_BODY: font: Playfair Display, color: #ffffff, size: 16pt, spacing: 20pt
* Introduction Slide
:PROPERTIES:
:ID: intro_slide
:END:
** Main Title
:PROPERTIES:
:TYPE: header
:AREA: b1,c4
:PADDING: 8,8
:JUSTIFY:
:Z: 10
:END:
Welcome to pagemaker
** Background Rectangle
:PROPERTIES:
:TYPE: rectangle
:AREA: A1,L4
:COLOR: #3498db
:ALPHA: 0.2
:Z: -1
:END:
** Demo Image
:PROPERTIES:
:TYPE: figure
:AREA: A5, H12
:PADDING: 0,0,0,0
:FIT: cover
:Z: -1
:END:
[[file:assets/test-images/landscapes/landscape-1.jpg]]
** poem
:PROPERTIES:
:TYPE: body
:STYLE: white_body
:AREA: C7,D10
:valign: top
:END:
I am but a leaf
Clinging to the tree of life
In the worldβs garden.
** poem
:PROPERTIES:
:TYPE: subheader
:STYLE: white_body
:AREA: E7,F10
:align: right
:valign: middle
:END:
Last night I saw you,
A dream rose and I your stem
Showing you the sun.
typst-pagemaker/
βββ src/ # Source code
β βββ pagemaker/ # Package (parser, generator, CLI)
βββ bin/ # Build tools and scripts
β βββ Makefile # Build automation
β βββ debug_test_fonts.sh
βββ examples/ # Example Org files and outputs
β βββ assets/ # Fonts and test resources
β β βββ fonts/ # Downloaded fonts
β β βββ test-images/ # Sample images for testing
β β βββ test-pdfs/ # Sample PDFs for testing
βββ tests/ # Test suite
β βββ unit/ # Unit tests
β βββ integration/ # Integration tests
β βββ fixtures/ # Test data
βββ docs/ # Documentation
PDF Mode:
| Property | Values | Description |
|---|---|---|
:TYPE: | header, subheader, body, figure, pdf, svg, rectangle, toc | Element type |
:AREA: | A1, B3,F5 | Grid position (A1 notation) |
:Z: | 10, 100 | Stacking order (higher on top) |
:PADDING: | 4, 2,4, 2,4,6,8 | Margin in mm (CSS TRBL) |
:ALIGN: | left, center, right | Horizontal alignment |
:VALIGN: | top, middle, bottom | Vertical alignment (text + pdf elements) |
:JUSTIFY: | (bare) or true/false | Full text justification |
:IGNORE: | true, false | When true: drop this page (level 1) or this section and its subtree (level β₯2). If :TYPE: is missing or none, only the element is omitted; children still parse. |
Story Mode:
| Property | Values | Description |
|---|---|---|
:BACKGROUND: | path/to/image.jpg | Full-section background image |
:STYLE: | background: #f0f0f0; color: #333; | Custom CSS for section |
:IGNORE: | true, false | Skip section in output |
Both Modes:
[[file:path/to/file.jpg]] (recommended) or :SRC: property*bold*, italic /italic/, code ~code~, links [[url][text]]PDF Mode:
| Header | Example | Description |
|---|---|---|
#+PAGESIZE: | A4, A3, A1 | Page size |
#+ORIENTATION: | landscape, portrait | Page orientation |
#+GRID: | 12x8, 16x9 | Grid dimensions |
#+MARGINS: | 10,15,10,15 | Margins in mm (TRBL) |
#+GRID_DEBUG: | true, false | Show debug grid |
Story Mode:
| Header | Example | Description |
|---|---|---|
#+TITLE: | My Story | Document title (optional) |
Story Mode ignores page size, orientation, grid, and margins settings. Layout is handled automatically.
** Header Text
:PROPERTIES:
:TYPE: header
:AREA: A1,F2
:END:
** Image
:PROPERTIES:
:TYPE: figure
:AREA: G1,L4
:FIT: contain
:END:
[[file:path/to/image.jpg]]
** PDF Page
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:AREA: A5,F8
:END:
[[file:path/to/doc.pdf]]
** Colored Rectangle
:PROPERTIES:
:TYPE: rectangle
:AREA: B2,K7
:COLOR: #3498db
:ALPHA: 0.3
:END:
PAGESIZE and ORIENTATION. Per-page overrides are ignored during Typst generation; the validator warns if pages disagree.:AREA: always addresses the total grid (including margin tracks); there is no :COORDS: directive.:IGNORE: true on a page (level 1) removes the entire page from the IR; following sections under that page are also ignored until the next page.:IGNORE: true on a section (level β₯2) removes that section and its entire subtree.:TYPE: is omitted or explicitly set to none, the element itself is omitted from the IR but its children are still parsed/emitted if they declare a valid :TYPE:.The validate subcommand parses Org -> IR, then enforces structural rules.
Errors (fail the build):
Warnings (reported but do not fail):
To escalate missing asset warnings into errors (e.g., for CI pipelines), use:
pagemaker validate --strict-assets examples/sample.org
This makes missing figure/pdf assets fail validation (non-zero exit code).
Example:
pagemaker validate examples/sample.org
Exit code 0 means no errors (warnings may still appear).
PADDING: t | t,r | t,r,b | t,r,b,l. Applies to text (header/subheader/body), figures, SVG, and PDF.:JUSTIFY: (bare) or :JUSTIFY: true enables full justification; false disables. Maps to Typst par(justify: true) wrapping.left, center, right. Applies to text (header, subheader, body) and media (figure, svg, pdf, toc).top, middle, bottom. Applies to text elements. Note: middle maps to Typst horizon (Typstβs vertical-center token).normal, bottom-up, center-out. Emitted as a comment for visibility, and when :VALIGN: is not set it can imply vertical alignment: bottom-up -> bottom, center-out -> horizon. Otherwise, explicit :VALIGN: wins.Essential external tools:
typst: Required for all document compilationmutool (MuPDF): Essential for PDF processing, SVG/PNG fallback generation, and full --sanitize-pdfs functionalityOptional external tools that enhance PDF handling with --sanitize-pdfs:
qpdf: Repairs and normalizes PDF structure (stream recompress, object streams)gs (Ghostscript): Alternate PDF distillation and PNG fallback renderingThe CLI automatically detects these tools. If unavailable, related stages are skipped, but missing essential tools will limit core functionality.
See the in-depth guide: docs/master_styles.md (styles, paragraph options, master pages, margins/grid, and padding semantics including zero-sum).
#+STYLE_<NAME>: where <NAME> is case-insensitive. Built-ins: HEADER, SUBHEADER, BODY.pt, em)#hex, rgb(...), hsl(...), or named):STYLE: to the style name (e.g., hero). If omitted, the elementβs type is used as the style key (header, subheader, body).rgb(50%,50%,50%)).Example:
#+STYLE_HEADER: font: Inter, weight: 900, size: 30pt, color: #ff00aa
#+STYLE_BODY: font: Inter, color: rgb(50%,50%,50%)
#+STYLE_HERO: font: Inter, weight: bold, size: 36pt, color: #123456
* Title
:PROPERTIES:
:TYPE: header
:AREA: 1,1,6,1
:END:
My Header
** Big Title
:PROPERTIES:
:TYPE: body
:STYLE: hero
:AREA: 1,2,12,2
:END:
Big Title
See examples/custom_styles_demo.org for a complete, runnable example.
par(...):
leading: Line leading (Typst length, e.g., 1.4em, 14pt).spacing: Space between paragraphs (length).first-line-indent (or first_line_indent): Indent the first line (length).hanging-indent (or hanging_indent): Hanging indent for subsequent lines (length).linebreaks: Typst line-breaking mode token (e.g., auto, loose, strict).justify: Boolean or token; when set, maps to justify: true|false.:JUSTIFY: always overrides the styleβs justify value.Paragraphs are split by:
--- or :::If a text block splits into multiple paragraphs, each paragraph is wrapped with par(...). Paragraphs are concatenated without extra blank lines; the visible gap is controlled by the styleβs spacing value. If spacing is omitted, the next paragraph appears as a line break with minimal separation. When there is a single paragraph and no paragraph options or justification are set, the text is emitted without a par(...) wrapper for backward compatibility.
Example (Org):
#+STYLE_BODY: font: Inter, leading: 1.4em, spacing: 1em, first-line-indent: 2em, hanging-indent: 1em, linebreaks: loose, justify: false
** Styled Body
:PROPERTIES:
:TYPE: body
:AREA: A1,L8
:JUSTIFY: true # element-level override
:END:
First paragraph line one.
---
Second paragraph, now with the styleβs paragraph options and justify enabled.
The package includes professional bundled fonts as a reliable default, with support for rich project-specific font libraries.
Font Resolution Order:
assets/fonts/ (custom library checked first)Bundled Fonts (Always Available):
Project Font Library:
# Add custom fonts to your project
mkdir -p assets/fonts/FontFamily
cp path/to/FontFamily-*.ttf assets/fonts/FontFamily/
# Fonts are automatically discovered and available in your documents
Font Management CLI:
# List all available fonts
pagemaker fonts list-all
# Show bundled fonts only
pagemaker fonts list-bundled --details
# Show project fonts only
pagemaker fonts list-project --details
# Validate specific font availability
pagemaker fonts validate "Inter"
pagemaker fonts validate "Your Custom Font"
Using Custom Fonts:
# Reference any available font in your documents
#+CUSTOM_STYLE: #set text(font: "Your Custom Font", size: 12pt)
* Heading with Custom Typography
#set text(font: "Playfair Display", weight: "bold", size: 18pt)
This heading uses a custom display font for elegant typography.
#set text(font: "Inter")
This paragraph switches back to the reliable bundled Inter font.
Font Discovery:
The system automatically includes all font paths in the correct precedence order. Project fonts in assets/fonts/ take priority over bundled fonts, ensuring reliable defaults with easy customization.
The pagemaker CLI includes a comprehensive font management system to help discover, install, analyze, and preview fonts in your projects.
List all fonts available to your project:
# Show all available fonts (project + bundled + system)
pagemaker fonts list-all
# Show only bundled fonts with details
pagemaker fonts list-bundled --details
# Show only project fonts with details
pagemaker fonts list-project --details
# Validate specific font availability
pagemaker fonts validate "Inter"
pagemaker fonts validate "Playfair Display"
Search and install fonts directly from Google Fonts:
# Search for fonts by name
pagemaker fonts search "Playfair"
pagemaker fonts search "mono" --limit 10
# Install fonts to your project
pagemaker fonts install "Playfair Display"
pagemaker fonts install "JetBrains Mono" --variants regular,700,italic
# Clear font installation cache
pagemaker fonts cache-clear
Installation Details:
assets/fonts/FontFamily/ directory structureAnalyze your documents to find font references and check availability:
# Analyze font usage in a document
pagemaker fonts analyze examples/sample.org
# Analyze with installation suggestions for missing fonts
pagemaker fonts analyze examples/font_management_demo.org
Analysis Features:
#+CUSTOM_STYLE and #set text(font: "Name") patternsGenerate font showcase documents to preview and compare fonts:
# Generate comprehensive font specimen
pagemaker fonts specimen my-fonts.org
# Generate simple comparison format
pagemaker fonts specimen fonts-comparison.org --format comparison
# Generate simple list format
pagemaker fonts specimen fonts-list.org --format simple
# Auto-build PDF after generating specimen
pagemaker fonts specimen my-fonts.org --build-pdf
Specimen Formats:
Integrate font validation into your build process:
# Build with font validation (warnings only)
pagemaker build examples/sample.org --validate-fonts
# Build with strict font validation (fails on missing fonts)
pagemaker pdf examples/sample.org --strict-fonts --pdf-output output.pdf
# Watch mode with font validation
pagemaker watch examples/sample.org --validate-fonts --pdf
Validation Features:
--validate-fonts: Shows warnings but continues build--strict-fonts: Fails build on missing fonts (useful for CI/CD)The font system includes caching for improved performance:
Complete workflow for adding a new font:
# 1. Search for desired font
pagemaker fonts search "Crimson"
# 2. Install the font
pagemaker fonts install "Crimson Pro"
# 3. Verify installation
pagemaker fonts validate "Crimson Pro"
# 4. Generate specimen to preview
pagemaker fonts specimen fonts-preview.org --format showcase
# 5. Use in your document
echo '#+CUSTOM_STYLE: #set text(font: "Crimson Pro", size: 12pt)' >> my-doc.org
# 6. Build with font validation
pagemaker pdf my-doc.org --validate-fonts --pdf-output my-doc.pdf
Analyzing and fixing font issues:
# Analyze document for font problems
pagemaker fonts analyze problematic-doc.org
# Output might show:
# β Missing: "Custom Font" - try: pagemaker fonts install "Custom Font"
# β Available: "Inter"
# Install missing fonts as suggested
pagemaker fonts install "Custom Font"
# Rebuild with validation
pagemaker pdf problematic-doc.org --strict-fonts --pdf-output fixed-doc.pdf
pagemaker provides a unified media embedding system with powerful sizing and alignment controls. All media types share a consistent property interface and support advanced features like fit modes, alignment, and captions.
All media elements (figure, pdf, svg) support these common properties:
| Property | Values | Description |
|---|---|---|
[[file:...]] | Path or URL | Native org-mode link syntax (recommended) |
:SRC: | Path or URL | Alternative property-based syntax |
:FIT: | contain, cover, stretch | How media scales within its frame |
:ALIGN: | left, center, right | Horizontal alignment within frame |
:VALIGN: | top, middle, bottom | Vertical alignment within frame |
:PADDING: | 4, 2,4, 2,4,6,8 | Internal padding in mm (CSS TRBL) |
:CAPTION: | Text | Caption text (figure and pdf) |
:PAGE: | Number | Select page from multi-page PDF (figure and pdf) |
:Z: | Number | Stacking order |
Migration Note: Legacy :PDF: and :SVG: properties are deprecated. Use [[file:...]] links (recommended) or :SRC: property instead.
The :FIT: property controls how media scales to fill its frame (defined by :AREA: minus :PADDING:):
contain (default): Scales media to fit completely within the frame while preserving aspect ratio. Media is centered with empty space (letterboxing) if aspect ratios don't match. Use :ALIGN: and :VALIGN: to reposition within the frame.
** Logo (centered, no cropping)
:PROPERTIES:
:TYPE: figure
:FIT: contain
:AREA: B2,D4
:END:
[[file:assets/logo.png]]
cover: Scales media to completely fill the frame while preserving aspect ratio. Media is cropped if aspect ratios don't match. Use :ALIGN: and :VALIGN: to control which part is visible.
** Hero Image (fills area, crops edges)
:PROPERTIES:
:TYPE: figure
:FIT: cover
:ALIGN: center
:VALIGN: middle
:AREA: A1,L4
:END:
[[file:assets/hero.jpg]]
stretch: Distorts media to exactly match frame dimensions, ignoring aspect ratio. Rarely needed but useful for precise graphic alignment.
** Exact Fit (may distort)
:PROPERTIES:
:TYPE: figure
:FIT: stretch
:AREA: A1,L8
:END:
[[file:assets/bg-pattern.png]]
Alignment properties control positioning within the element frame:
:ALIGN: / :VALIGN:: Media is positioned accordingly
contain mode: Controls placement of letterboxed mediacover mode: Controls which part of the cropped media is visibleCover Mode Cropping Details:
In cover mode, media is scaled to completely fill the frame, and overflow is cropped. Alignment determines which part remains visible:
Horizontal alignment (:ALIGN:):
left: Left edge visible, right edge croppedcenter: Center visible, both edges cropped equally (default)right: Right edge visible, left edge croppedVertical alignment (:VALIGN:):
top: Top visible, bottom croppedmiddle: Middle visible, top and bottom cropped equally (default)bottom: Bottom visible, top croppedExample: Cover mode with alignment to focus on specific area:
** Portrait Photo (focus on face)
:PROPERTIES:
:TYPE: figure
:FIT: cover
:ALIGN: center
:VALIGN: top # Keep top portion visible (face)
:AREA: C2,E6
:END:
[[file:assets/portrait.jpg]]
Example: Landscape photo with left-aligned crop:
** Landscape (focus on left side)
:PROPERTIES:
:TYPE: figure
:FIT: cover
:ALIGN: left # Keep left edge visible
:VALIGN: middle
:AREA: B3,F5
:END:
[[file:assets/landscape.jpg]]
Figure Elements (figure): For raster images and general media embedding
** Product Photo
:PROPERTIES:
:TYPE: figure
:FIT: cover
:CAPTION: Premium Widget - Model XL
:AREA: B2,F6
:END:
[[file:assets/product.jpg]]
PDF Elements (pdf): For embedded PDF pages with precise sizing
** Technical Specification
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:FIT: contain
:CAPTION: System Architecture Diagram
:AREA: D2,I6
:END:
[[file:assets/spec.pdf]]
Cover Mode Example: PDF cropped to fill area with alignment control:
** Blueprint Detail
:PROPERTIES:
:TYPE: pdf
:FIT: cover
:ALIGN: left
:VALIGN: top
:AREA: C3,H7
:END:
[[file:assets/plans.pdf]]
SVG Elements (svg): For vector graphics with intrinsic sizing
** Vector Logo
:PROPERTIES:
:TYPE: svg
:FIT: contain
:ALIGN: center
:VALIGN: middle
:AREA: A1,C2
:END:
[[file:assets/logo.svg]]
SVG Sizing: The system intelligently detects SVG intrinsic size from viewBox, width, height attributes, and falls back to content bounding box analysis for proper scaling.
Cover Mode Example: SVG cropped to fill area with alignment:
** Icon Background
:PROPERTIES:
:TYPE: svg
:FIT: cover
:ALIGN: center
:AREA: B2,D4
:END:
[[file:assets/pattern.svg]]
Both figure and pdf elements support captions:
** Captioned Image
:PROPERTIES:
:TYPE: figure
:FIT: contain
:CAPTION: Q4 Sales Performance - Up 23% YoY
:AREA: A5,F8
:END:
[[file:assets/chart.png]]
Caption Behavior:
The unified architecture allows flexible cross-type capabilities:
figure with :PAGE: to embed PDF pagespdf with :CAPTION: for captioned document pages[[file:...]] links or :SRC: propertyFull-bleed background image:
** Background
:PROPERTIES:
:TYPE: figure
:FIT: cover
:AREA: A1,L8
:Z: -10
:END:
[[file:assets/texture.jpg]]
Contained logo with padding:
** Company Logo
:PROPERTIES:
:TYPE: svg
:FIT: contain
:PADDING: 10
:ALIGN: center
:VALIGN: middle
:AREA: A1,B2
:END:
[[file:assets/logo.svg]]
PDF page with specific focus:
** Blueprint Detail
:PROPERTIES:
:TYPE: pdf
:PAGE: 3
:ALIGN: left
:VALIGN: top
:AREA: C3,H7
:CAPTION: Ground Floor Detail
:END:
[[file:assets/plans.pdf]]
For problematic PDFs, use the --sanitize-pdfs flag:
pagemaker pdf document.org --sanitize-pdfs --pdf-output output.pdf
If sanitization fails, pagemaker automatically falls back to SVG (preferred) or PNG conversion for the requested page. Fallback assets are written to export_dir/assets/pdf-fallbacks/.
For missing media, use strict validation:
pagemaker validate document.org --strict-assets
See examples/test_image_fit.org for a comprehensive comparison of fit modes across different media types.
pagemaker supports HTML export alongside PDF generation, allowing you to create web-ready documents from your Org-mode source files.
Generate HTML output using the --html flag:
# PDF only (default)
pagemaker pdf document.org
# HTML only
pagemaker pdf document.org --html
# Both PDF and HTML
pagemaker pdf document.org --pdf --html
# Watch mode with HTML
pagemaker watch document.org --pdf --html
Output Structure:
export/
document.pdf # PDF output
document/ # HTML output directory
index.html # Main HTML file
Working Features:
assets/ directory for reference (Typst embeds them automatically)Use Cases:
The current HTML export (M7) focuses on content-focused output rather than presentation layout:
β οΈ Layout Limitations:
:AREA: properties are ignored in HTMLThese limitations will be addressed in M7.5: HTML Grid Layout (planned), which will add:
:AREA: positioningChoose HTML when you need:
Choose PDF when you need:
Use Both when:
See these examples for HTML export demonstrations:
examples/svg_demo.org - SVG embedding in HTMLexamples/media_consolidation_demo.org - Mixed media (images, PDFs)Create transparent overlays and design elements:
** Background Accent
:PROPERTIES:
:TYPE: rectangle
:AREA: B2,I6
:COLOR: #FF6B6B
:ALPHA: 0.3
:Z: 10
:END:
Rectangle style keys and behavior:
#hex, rgb(...), hsl(...), named)pt|mm|cm|in)Emission rules:
ColorRect("<color>", <alpha>) when no stroke/radius providedColorRect(..., stroke: ..., stroke_color: ..., radius: ...)stroke: none, stroke_color: none with provided radiusDefine outer margins in millimeters that expand the total grid while keeping your content coordinates stable. Format: top,right,bottom,left (CSS TRBL order).
#+GRID: 12x8
#+MARGINS: 10,15,10,15
* Slide
:PROPERTIES:
:ID: s1
:END:
** Full-bleed background (uses margin tracks)
:PROPERTIES:
:TYPE: rectangle
:AREA: 1,1,14,10
:COLOR: #3498db
:ALPHA: 0.1
:END:
** Content inside margins
:PROPERTIES:
:TYPE: body
:AREA: A1,L8
:END:
The content grid remains 12x8, but the total grid has one margin track on each side. Content coordinates map to total with a +1,+1 offset when margins are present.
Notes:
MARGINS values are absolute sizes in mm.:AREA: always addresses the total grid (including margin tracks). The content grid remains your declared GRID inside the margins; when margins are present, content coordinates map to total with a +1,+1 offset.#+GRID_DEBUG: true, the overlay shows the total grid (including margin tracks). Labels cover all tracks: first column is 1, first row is A.See examples/master_pages_demo.org for a runnable master page setup.
Define reusable element sets as master pages that are not directly rendered. Apply them per slide with :MASTER: or globally with #+DEFAULT_MASTER:.
#+DEFAULT_MASTER: Base
* Base Master (not rendered)
:PROPERTIES:
:MASTER_DEF: Base
:END:
** Header Bar
:PROPERTIES:
:TYPE: rectangle
:AREA: A1,A12
:COLOR: #000000
:ALPHA: 0.08
:END:
** Footer Text
:PROPERTIES:
:TYPE: body
:AREA: H11,H12
:END:
Page #page_no / #page_total β #date_dd_mm_yy
* Slide One (inherits Base)
:PROPERTIES:
:ID: s1
:END:
** Title
:PROPERTIES:
:TYPE: header
:AREA: B2,C11
:END:
Welcome with Master
Notes:
:MASTER_DEF: are used as master definitions and are skipped at render time.:MASTER: or inherit from #+DEFAULT_MASTER:.Story Mode is an alternative HTML export format that transforms your org-mode documents into modern, scrolling web narratives with automatic grid layout. Unlike the standard HTML export (content-focused, sequential flow), Story Mode provides a presentation-like experience optimized for web viewing.
Generate a Story Mode HTML export:
# Generate story mode HTML (inline CSS/JS, fully self-contained)
pagemaker story document.org
# Generate with separate CSS/JS files (easier to customize)
pagemaker story document.org --separate-assets
# Watch mode: auto-rebuild on file/asset changes
pagemaker watch document.org --story
pagemaker watch document.org --story --separate-assets
# Custom output location
pagemaker story document.org --export-dir web/
# Open in browser after generation
pagemaker story document.org && open export/index.html
Output Structure (Default - Inline):
export/
index.html # Self-contained HTML with inline CSS/JS
assets/ # Media assets (images, SVGs, PDFs)
image1.jpg
diagram.svg
Output Structure (Separate Assets):
export/
index.html # HTML with external CSS/JS references
story.css # Separate CSS file (customizable)
story.js # Separate JavaScript file (customizable)
assets/ # Media assets (images, SVGs, PDFs)
image1.jpg
diagram.svg
Visual Design:
:BACKGROUND: property:STYLE: propertyContent Support:
Navigation:
Asset Handling:
Basic Document Structure:
#+TITLE: My Story
* Introduction Section
Content for the first full-viewport section.
* Main Content
Another section - each level-1 heading creates a new full-screen area.
** Subsection
Level-2+ headings create content blocks within the section.
Background Images:
Add full-section background images using the :BACKGROUND: property:
* Hero Section
:PROPERTIES:
:BACKGROUND: assets/hero-image.jpg
:END:
** Welcome Title
This section has a full-screen background image behind all content.
Custom Section Styles:
Apply custom CSS styling to individual sections:
* Styled Section
:PROPERTIES:
:STYLE: background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;
:END:
** Custom Appearance
This section has a gradient background and white text.
Media Embedding:
Story Mode supports all pagemaker media types:
* Visual Content
** Hero Image
:PROPERTIES:
:TYPE: figure
:END:
[[file:assets/photo.jpg]]
** Technical Diagram
:PROPERTIES:
:TYPE: svg
:END:
[[file:assets/diagram.svg]]
** Document Page
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:END:
[[file:assets/spec.pdf]]
Tables and Lists:
* Data Section
** Sales Results
| Product | Q1 | Q2 | Q3 | Q4 |
|---------+----+----+----+----|
| Widget | 45 | 52 | 61 | 58 |
| Gadget | 23 | 31 | 35 | 42 |
** Key Features
- Automatic grid layout
- Responsive design
- Smooth scrolling
- Keyboard navigation
Story Mode automatically arranges content blocks (level-2+ headings) using a responsive grid system:
Each section (level-1 heading) fills the viewport and contains auto-placed content blocks.
| Feature | Story Mode | Standard HTML Export |
|---|---|---|
| Layout | Auto-grid, full-viewport sections | Sequential, flowing content |
| Navigation | Keyboard shortcuts, smooth scroll | Standard browser scroll |
| Media | All types, asset copying | All types, base64 embedded |
| Use Case | Web presentations, portfolios, narratives | Readable documents, archival |
| Grid positioning | Automatic (ignores :AREA:) | N/A (ignores :AREA:) |
| Output | Modern web experience | Content-focused HTML |
Use Story Mode when you need:
Use Standard HTML when you need:
Use PDF when you need:
See these examples for Story Mode demonstrations:
examples/story_demo.org - Basic story mode with auto-layoutexamples/story_background_demo.org - Background imagesexamples/story_tables_lists_demo.org - Tables and listsexamples/story_media_demo.org - Images, SVGs, and PDFsSeparate CSS/JS Files:
For easier customization, use the --separate-assets flag to generate external CSS and JavaScript files:
# Generate with separate assets
pagemaker story document.org --separate-assets
# Output: index.html, story.css, story.js, assets/
This creates:
story.css - All styling (fully customizable)story.js - Navigation logic (keyboard shortcuts, scrolling)index.html - Clean HTML with external referencesOverride Styles:
Edit the generated story.css to customize:
Example customizations in story.css:
/* Change default font and colors */
body {
font-family: "Georgia", serif;
color: #2c3e50;
background: #ecf0f1;
}
/* Customize section backgrounds */
.scene {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
/* Style headings */
.block-header h1 {
font-size: 3rem;
color: #ffffff;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
/* Adjust grid spacing */
.grid-container {
gap: 2rem; /* Default is 1.5rem */
padding: 3rem; /* Default is 2rem */
}
Extend Navigation:
Edit story.js to add:
Example Workflow (One-time Build):
# 1. Generate with separate assets
pagemaker story presentation.org --separate-assets
# 2. Customize the CSS
nano export/story.css # Edit colors, fonts, etc.
# 3. Regenerate content (preserves your CSS edits if you keep backups)
# Best practice: version control your customized CSS/JS
Development Workflow (Watch Mode):
# Auto-rebuild on changes (recommended for development)
pagemaker watch presentation.org --story --separate-assets
# Now you can:
# 1. Edit presentation.org - auto-rebuilds HTML
# 2. Edit export/story.css - refresh browser to see changes
# 3. Modify referenced assets - auto-rebuilds HTML
# 4. Keep browser open, changes appear on refresh
Watch mode monitors your org file and all referenced assets (images, SVGs, PDFs) for changes. When any file is modified, the HTML is automatically regenerated. This is ideal for iterative development where you're frequently adjusting content and styling.
Best Practice: Keep your customized CSS/JS under version control separate from the export directory, then copy them over after regenerating content.
Security:
Asset Management:
image.jpg, image_1.jpg)export/assets/Browser Compatibility:
pagemaker ships a CLI, and an optional Emacs minor mode (org-pagemaker) to drive the CLI from Org buffers. This section shows how to install and use it.
;; Stable: pin to a released tag (recommended)
(use-package org-pagemaker
:straight (org-pagemaker
:type git
:host github
:repo "sanderboer/org-pagemaker"
:tag "v0.1.2" ;; pin to a release tag (if available)
:files ("lisp/*.el"))
:hook (org-mode . org-pagemaker-mode))
;; (use-package org-pagemaker
;; :straight (org-pagemaker :type git :host github :repo "sanderboer/org-pagemaker" :files ("lisp/*.el"))
;; :hook (org-mode . org-pagemaker-mode))
Notes:
The Hydra is an optional convenience. If hydra is not present, C-c p h displays a helpful message; all other keybindings continue to work.
make test
# or
python -m unittest discover tests -v
pagemaker pdf end-to-end and compiles via Typst. It automatically skips if typst is unavailable.This project uses pre-commit with Ruff for formatting and linting.
Setup:
pip install pre-commit
pre-commit install
Run hooks on the entire repo:
pre-commit run --all-files
Tools:
ruff-format)Current temporary linter ignores (to keep commits unblocked):
Run Ruff manually:
ruff format .
ruff check . --fix
We plan to remove the temporary ignores as the codebase is modernized.
MIT License - see LICENSE file for details.
Created for building Typst-based slide decks from Org-mode.
For more detailed documentation, examples, and advanced usage patterns, see the docs/ directory and examples/ folder.
FAQs
Structured document-to-page layout system for Typst with explicit positioning and professional typography
We found that typst-pagemaker demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: whatβs affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.

Security News
GitHub has revoked npm classic tokens for publishing; maintainers must migrate, but OpenJS warns OIDC trusted publishing still has risky gaps for critical projects.