Crispy Print
Print system based on Typst using Vue UI on top of Frappe Frameworks 【矢量打印】
- Author: agatho-daemon
- Repository: https://github.com/agatho-daemon/crispy_print
- GitHub stars: 12
- Forks: 10
- License: MIT
- Category: Developer Tools
- Maintenance: Actively Maintained
- Frappe versions: develop
Install Crispy Print
bench get-app https://github.com/agatho-daemon/crispy_print
Tags
- frappe
- pdf-generation
- typst
- vector-printing
Add the Frappe Gems badge to your README
Maintain Crispy Print? Paste this into your README:
[](https://frappegems.com/gems/apps/agatho-daemon/crispy_print)
About Crispy Print
Crispy Print
Modern print format designer for Frappe using the Typst typesetting system. Build PDF‑native print formats with a Vue 3 visual builder and real-time preview.
Project Status
Alpha / Work in progress. Expect frequent changes while features are still settling.
> Why Typst instead of HTML/CSS? Typst provides superior PDF typography, precise layout control, and professional typesetting features that are difficult to achieve with browser-based rendering. Perfect for invoices, reports, certificates, and other print-critical documents.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Usage
- Font Configuration
- Architecture
- Development
- API Reference
- Known Limitations
- Roadmap
- Troubleshooting
- FAQ
- Testing
- Contributing
- License
Features
- Visual Print Format Builder - Drag-and-drop interface for designing print layouts
- Real-time Typst Preview - See PDF output as you design with live SVG preview
- Native PDF Generation - High-quality PDFs via Typst CLI (no browser printing)
- DocType Integration - Create custom formats for any Frappe DocType
- Letterhead Support - Use Letter Head documents with automatic image handling
- Logo Support - Add company logo to page.
- Custom Fonts - Support for system fonts, custom fonts, and bundled fonts
- Print Preview Page - Dedicated preview page for testing formats with actual documents
- QR Code Integration - Automatic QR code generation for documents
- Raw Typst Mode - Advanced users can write Typst markup directly
- Dual-Mode Report Builder - Basic visual controls for report templates with Advanced Raw Typst mode for full customization
- Report Mode Guardrails - Safe Basic/Advanced switching with signature checks to prevent accidental overwrite of custom Typst
Requirements
Typst CLI (Required)
Typst must be installed on your system before installing the app.
macOS (Homebrew)
brew install typst
Linux (Ubuntu/Debian) & Windows WSL
curl -L -o typst.tar.xz https://github.com/typst/typst/releases/latest/download/typst-x86_64-unknown-linux-musl.tar.xz
tar -xf typst.tar.xz
sudo mv typst-x86_64-unknown-linux-musl/typst /usr/local/bin/
> Windows users: Frappe requires WSL. Install Typst inside your WSL environment using the Linux commands above.
Or download from Typst Releases
Verify Installation
typst --version
# Should output: typst 0.11.0 or higher
Frappe Compatibility
- Frappe: v15 or later (all Python/Node.js dependencies already satisfied)
- Python dependency:
pyqrcode(installed with the app; required for QR SVG generation)
Installation
1. Install Typst CLI
See Requirements above - Typst must be installed first.
2. Get and Install the App
cd ~/frappe-bench
bench get-app https://github.com/agatho-daemon/crispy_print --branch develop
bench --site your-site install-app crispy_print
bench restart
3. Verify Installation
# Check app is installed
bench --site your-site list-apps | grep crispy_print
# Test Typst integration
bench --site your-site console
>>> from crispy_print.api import get_typst_local_fonts
>>> fonts = get_typst_local_fonts()
>>> print(len(fonts), "fonts available")
4. Build Assets (Development Only)
If you're developing the app:
cd apps/crispy_print/crispy_print/public/js
yarn install
cd ~/frappe-bench
bench build --app crispy_print
Quick Start
Creating Your First Print Format
> ⚠️ CRITICAL: You must set at least one format as Default for a DocType. The Typst print button appears on document forms only when a default format exists for that DocType.
Step-by-step:
Create a new format
- Navigate to: Desk → Crispy Print → Crispy Format
- Click New
- Enter Name (e.g., "Sales Invoice Modern")
- Select DocType (e.g., "Sales Invoice")
- Select Module (e.g., "Crispy Print")
- Save
Set as default ⚠️ (Required for button to appear!)
- Check the "Set as Default" checkbox
- Save again
Design your layout
- Click Open Builder button
- Add sections: Click "+ Add Section"
- Drag fields: From right pane to layout grid
- Configure fields: Click field to edit label, style, alignment
- Add tables: Drag table fields (e.g., "items") for line items
- Adjust columns: Split sections into 1-4 columns
Configure page settings (left sidebar)
- Paper Size: A4, Letter, etc.
- Margins: Adjust spacing
- Fonts: Select font family
- Letterhead: Optional background image
- QR Code: Enable for verification
Save and test
- Click Save
- Open any document of that DocType (e.g., Sales Invoice)
- Look for Typst button in toolbar (top-right)
- Click to preview and download PDF
Using Your Print Format
Once a default format exists, the Typst button appears automatically on all documents of that DocType.
From Document: 1. Open document (e.g., SI-2024-001) 2. Click Typst button in toolbar 3. Preview opens with your default format 4. Click Download PDF
Direct URL:
/app/crispy-print/{doctype}/{docname}/{format_name}
Font Configuration
Bundled Fonts
The app automatically includes fonts from crispy_print/public/vendor/typst/. These fonts are available to all print formats without additional configuration.
System Fonts
Typst automatically discovers system fonts. On Linux, it searches standard directories like /usr/share/fonts and ~/.local/share/fonts.
Custom Fonts
To add custom fonts outside the Frappe bench:
Option 1: Environment Variable (Recommended)
Add to your shell profile (~/.bashrc, ~/.zshrc, or ~/.profile):
export TYPST_FONT_PATHS="/path/to/custom/fonts:/another/font/path"
Then restart your bench:
bench restart
Option 2: Typst Font Directory
Set the dedicated Typst font directory:
export TYPST_FONT_DIR="$HOME/.fonts/typst"
Create the directory and add fonts:
mkdir -p ~/.fonts/typst
cp /path/to/font.ttf ~/.fonts/typst/
Frappe Site Configuration
You can also configure the Typst binary path in site_config.json:
{
"TYPST_BIN": "/usr/local/bin/typst"
}
Font Discovery
The app's get_typst_local_fonts() API method returns all available fonts by running:
typst fonts
This includes:
- System fonts
- Fonts in TYPST_FONT_PATHS
- Bundled fonts from crispy_print/public/vendor/typst/
Architecture
Build System
This app uses Frappe v15's native esbuild bundler - no separate Vite or webpack setup required.
- Bundle Entry:
crispy_print/public/js/crispy_print.bundle.js - Build Command:
bench build --app crispy_print - Output: Single JavaScript bundle with inlined CSS (~1.7MB)
- Plugin: Uses
frappe-vue-styleto automatically inline Vue SFC styles
Project Structure
crispy_print/
├── crispy_print/
│ ├── api.py # Whitelisted API methods
│ ├── hooks.py # App hooks
│ ├── public/
│ │ ├── js/
│ │ │ ├── crispy_print.bundle.js # Main entry (builder)
│ │ │ ├── crispy_preview.bundle.js # Preview page entry
│ │ │ ├── components/ # Reusable Vue components
│ │ │ ├── composables/ # Vue composables (useStore)
│ │ │ ├── pages/
│ │ │ │ ├── CrispyPFB.vue # Print Format Builder
│ │ │ │ └── CrispyPP.vue # Print Preview
│ │ │ ├── typst/
│ │ │ │ ├── createTypstWorker.ts # Web worker factory
│ │ │ │ ├── setupWorker.ts # Worker orchestration
│ │ │ │ ├── JSONToTypst.ts # Layout → Typst translator
│ │ │ │ └── worker.ts # Typst compilation worker
│ │ │ └── utils/
│ │ │ ├── layout.ts # Layout type definitions
│ │ │ └── formatLoader.ts # Format data utilities
│ │ └── vendor/typst/ # Bundled fonts (optional)
│ ├── doctype/
│ │ └── crispy_format/ # Crispy Format DocType
│ └── page/
│ ├── crispy_print_builder/ # Builder page (Frappe desk)
│ └── typst_print/ # Preview page (Frappe desk)
├── pyproject.toml # Python dependencies & config
└── README.md
Key Components
Pages:
- Crispy Format Builder (/app/crispy-format-builder) - 4-pane builder; DocType uses visual layout, Report supports Basic + Advanced Raw Typst modes
- Crispy Print Preview (/app/crispy-print/{doctype}/{docname}/{format}) - Document preview page
Core Files:
- api.py - Backend API: Typst compilation, font discovery, letterhead handling
- CrispyPFB.vue - Main builder component with drag-drop layout editor
- CrispyPP.vue - Preview component with format/settings controls
- useStore.ts - Centralized state management (layout, page settings, metadata)
- setupWorker.ts - Typst worker lifecycle and compilation orchestration
- JSONToTypst.ts - Translates JSON layout structure to Typst markup
- worker.ts - Web Worker for async Typst compilation via API
- formatLoader.ts - Utilities for loading Crispy Format documents
Development
Frontend Dependencies
For TypeScript/Vue IntelliSense in VS Code and the color picker bundle (@simonwep/pickr):
cd apps/crispy_print/crispy_print/public/js
yarn install
This installs local dependencies used by the frontend bundle:
- package.json, yarn.lock - Type dependencies
- tsconfig.json - TypeScript configuration
- node_modules/ - Type definitions
Note: Required for building.
Building
# Build the app
bench build --app crispy_print
# Clear cache after changes
bench clear-cache && bench clear-website-cache
# Development workflow
bench start # Run with auto-reload enabled
Running Tests
Frontend Tests (TypeScript/Vue):
cd apps/crispy_print/crispy_print/public/js
# Run all tests
yarn test:unit
# Run specific batch
yarn test:unit:batch6
# Watch mode
yarn test:unit -- --watch
Backend Tests (Python):
# Run all tests
bench --site your-site run-tests --app crispy_print
# Run specific module
bench --site your-site run-tests --module crispy_print.tests.test_api
# Run DocType tests
bench --site your-site run-tests --doctype "Crispy Format"
Test Coverage: - Frontend: 67 tests across 27 test files (100% passing) - Backend: 29 tests across 2 test files (100% passing) - Total: 96 tests
See TEST_COVERAGE.md for details.
Vue Component Guidelines
All Vue components use `
For dynamically created DOM (e.g., `.typst-page` elements), apply styles via JavaScript:
```typescript
const page = document.createElement("div")
page.className = "typst-page"
page.style.marginBottom = "1.5rem"
page.style.boxShadow = "0 4px 12px rgba(148, 163, 184, 0.25)"
Usage
Print Format Workflow
Related Developer Tools apps for Frappe & ERPNext
- Frappe — Low code web framework for real world applications, in Python and Javascript
- Frappe Docker — Docker environment for developing, deploying, and running Frappe applications (ERPNext and custom apps) in production and development
- Builder — Craft beautiful websites effortlessly with an intuitive visual builder and publish them instantly
- Bench — CLI to manage Multi-tenant deployments for Frappe apps
- Frappe Ui — A set of components and utilities for rapid UI development
- Press — Full service cloud hosting for the Frappe stack - powers Frappe Cloud
- Gameplan — Open Source Discussions Platform for Remote Teams
- Doppio — A Frappe app (CLI) to magically setup single page applications and Vue/React powered desk pages on your custom Frappe apps.