Binary Protocol Quick Reference
Simple Explanation
Presto templates are not a bunch of files -- they are executable programs. You feed Markdown text in, and they produce typesetting code (Typst). It's that simple.
Imagine a black box: Markdown goes in on the left, Typst comes out on the right. This black box can also answer a few questions -- "Who are you?" (--manifest), "Got an example?" (--example), "What version?" (--version). The Presto application interacts with templates through these four methods and no others.
Template binaries run in a strict sandbox: 30-second timeout, no network access, no file writing, minimal environment variables. This means template code cannot steal data or cause damage.
Protocol Quick Reference
Five Invocation Methods
| Method | Command | stdin | stdout | Purpose |
|---|---|---|---|---|
| Convert | ./binary | Markdown text | Typst code | Core function: turn Markdown into typesetting code |
| Metadata | ./binary --manifest | None | manifest JSON | Extract template info during installation |
| Example | ./binary --example | None | Markdown text | Showcase template output |
| Version | ./binary --version | None | Version string | Version check and update detection |
| Info | ./binary --info | Markdown text | JSON | Output basename, preview title, and metadata |
Security Constraints
| Constraint | Value | Description |
|---|---|---|
| Execution timeout | 30 seconds | Maximum time per invocation |
| Build timeout | 300 seconds (5 minutes) | Maximum time for template build |
| Manifest size limit | 1 MB | --manifest output limit |
| Example size limit | 1 MB | --example output limit |
| Typst output limit | 10 MB | Conversion output limit |
| Build artifact limit | 50 MB | Compiled binary size limit |
| Environment variables | Only PATH=/usr/local/bin:/usr/bin:/bin | Minimal environment, no other variables |
| Network access | Prohibited | macOS sandbox-exec / Linux unshare --net |
| File writing | Prohibited | Output only via stdout |
| CLI flags | Only the five above | No additional flags beyond the protocol |
| Convert stdout | Non-empty Typst | Blank output after trimming must fail |
Three Layers of Security
| Layer | Mechanism | Purpose |
|---|---|---|
| Static analysis | Import blocklist | Block dangerous dependencies pre-build |
| Runtime sandbox | macOS sandbox-exec / Linux unshare --net | Isolate network and filesystem |
| Output validation | Non-empty and format checking | Ensure stdout contains non-empty Typst |
Interaction Sequence Diagram
Detailed Explanation
1. Convert: Core Function
This is the reason templates exist. Presto passes the user's Markdown to the template binary via stdin, and the binary processes it and returns Typst source code via stdout.
Internal processing flow:
splitFrontmatter()-- Separate the YAML header (page configuration) from the bodywritePageSetup()-- Generate Typst page setup code based on frontmatter fieldsrenderBody()-- Parse Markdown AST with goldmark, converting each node to Typst syntax
Key constraints:
- stdin accepts only Markdown text
- stdout must output non-empty valid Typst source code
- conversion failures must write stderr and exit non-zero
- templates must not swallow parse/render errors and return an empty string, blank Typst, or nearly empty success output
- Cannot read or write any files, cannot access the network
- Automatically terminated after 30 seconds
2. Metadata: --manifest
When installing a template, the first thing Presto does is call --manifest to get the template's self-description. This JSON tells Presto:
- The template's name, author, and version
- Which fonts are required
- Which frontmatter fields are supported (types, defaults, formats)
Manifest data is embedded in the binary at compile time via Go's //go:embed -- it's not generated at runtime.
3. Example: --example
Returns a sample Markdown document, used for:
- Preview display in the template store
- A starter template when users first use it
- Input data for automated testing
Also embedded via //go:embed.
4. Version: --version
Returns the version string, read from the version field of the embedded manifest.json. Used for:
- Checking if the template has updates
- Compatibility checks (in conjunction with
minPrestoVersion)
5. Embedding Mechanism
Templates follow a "binary embedding model," not a "file copying model." All resources are packaged into the executable at compile time:
//go:embed manifest.json
var manifestData []byte
//go:embed example.md
var exampleData []byteThis means:
- Distribution involves only a single file, with no additional resource directories needed
- No external file dependencies at runtime, eliminating "config not found" issues
- Sandbox restrictions are easier to enforce -- the binary doesn't need to read any external files
Complete manifest.json Example
{
"name": "academic-paper",
"displayName": "Academic Paper",
"description": "A Chinese academic paper template with abstract, keywords, and references",
"version": "1.2.0",
"author": "Zhang San <zhangsan@example.com>",
"license": "MIT",
"minPrestoVersion": "0.5.0",
"keywords": ["academic", "paper", "Chinese", "LaTeX alternative"],
"requiredFonts": [
{
"name": "NotoSerifCJKsc",
"displayName": "Noto Serif CJK SC",
"url": "https://github.com/notofonts/noto-cjk/releases"
},
{
"name": "NotoSansCJKsc",
"displayName": "Noto Sans CJK SC",
"url": "https://github.com/notofonts/noto-cjk/releases"
}
],
"frontmatterSchema": {
"title": {
"type": "string",
"default": "Untitled Paper"
},
"author": {
"type": "string",
"default": "Anonymous"
},
"date": {
"type": "string",
"format": "date"
},
"abstract": {
"type": "string",
"default": ""
},
"keywords": {
"type": "string",
"default": ""
},
"twocolumn": {
"type": "boolean",
"default": false
},
"fontsize": {
"type": "string",
"default": "12pt"
},
"papersize": {
"type": "string",
"default": "a4"
},
"margin": {
"type": "string",
"default": "2.5cm"
},
"linestretch": {
"type": "number",
"default": 1.5
}
}
}Field descriptions:
| Field | Required | Description |
|---|---|---|
name | Yes | Template unique identifier, lowercase + hyphens |
displayName | Yes | User-visible template name |
description | Yes | Template purpose description |
version | Yes | Semantic version number (semver) |
author | Yes | Author information |
license | Yes | Open source license |
minPrestoVersion | Yes | Minimum compatible Presto version |
keywords | No | Search keywords |
requiredFonts | No | List of required fonts |
frontmatterSchema | Yes | User-configurable frontmatter field definitions |
Supported type values in frontmatterSchema:
| type | Description | Example default |
|---|---|---|
"string" | Text | "Untitled Paper" |
"number" | Number | 1.5 |
"boolean" | Boolean | false |
The optional format field hints at UI rendering (e.g., "date" will display a date picker).
