RFC: .typy template package format and manifest v1¶
This document defines the portable template package format used by typy.
A .typy file is a self-contained, distributable unit that bundles a Python Template class, the Typst files it references, and any associated assets.
Overview¶
A .typy package is a ZIP archive with the .typy file extension.
The archive contains a mandatory manifest.json (the package descriptor) and a template.py file that defines the template data model as a subclass of typy.templates.Template.
Because it is plain ZIP, consumers can inspect and unpack it with any standard ZIP tool.
Container structure¶
my-template.typy ← ZIP archive with .typy extension
├── manifest.json ← REQUIRED: package descriptor (manifest v1)
├── template.py ← REQUIRED: Python file defining the Template subclass
├── templates/ ← REQUIRED: Typst files referenced by __template_path__ in template.py
│ └── template.typ
├── assets/ ← optional: images, fonts, or other static resources
│ ├── logo.png
│ └── font.ttf
└── README.md ← optional: human-readable notes for the package
Required files¶
File |
Description |
|---|---|
|
Package descriptor in JSON format conforming to manifest schema v1 (see below). |
|
Python module containing exactly one |
|
Directory containing the Typst file(s) referenced by |
Optional files¶
File/directory |
Description |
|---|---|
|
Static resources (images, fonts, etc.) referenced by the template. Paths must be relative and must stay inside the archive root. |
|
Package documentation for human readers. Shown by tools that display package info. |
Path rules¶
All paths inside the archive must be relative (no leading
/or..traversal).__template_path__intemplate.pyand any files it references must not escape the archive root via path traversal (../).File names are case-sensitive.
Manifest schema v1¶
The manifest.json file is UTF-8-encoded JSON.
The "manifest_version" field determines which schema applies.
This document specifies manifest version 1.
Fields¶
Field |
Type |
Required |
Description |
|---|---|---|---|
|
integer |
yes |
Schema version. Must be |
|
string |
yes |
Package identifier. Lowercase alphanumeric, hyphens allowed. Pattern: |
|
string |
yes |
Semantic version of this package, e.g. |
|
string |
yes |
One-line human-readable summary of the template’s purpose. |
|
string |
yes |
Author name, optionally with email in angle brackets, e.g. |
|
string |
yes |
PEP 440 version specifier for the typy version this package requires, e.g. |
|
array of strings |
no |
List of other |
|
string |
no |
SPDX license identifier, e.g. |
|
string |
no |
URL for the package’s home page or repository. |
|
array of strings |
no |
Tags for discovery. Each keyword: max 32 characters. |
Example: minimal valid manifest¶
{
"manifest_version": 1,
"name": "my-report",
"version": "1.0.0",
"description": "A general-purpose report template with cover page and TOC.",
"author": "Jane Doe <jane@example.com>",
"typy_compatibility": ">=0.1.0"
}
Example: full valid manifest¶
{
"manifest_version": 1,
"name": "corporate-invoice",
"version": "2.1.0",
"description": "Professional invoice template with logo, line items, and tax calculation.",
"author": "Acme Corp <templates@acme.example.com>",
"typy_compatibility": ">=0.2.0,<1.0.0",
"dependencies": [
"acme-base@>=1.0.0"
],
"license": "MIT",
"homepage": "https://github.com/acme/typy-templates",
"keywords": ["invoice", "billing", "business"]
}
Compatibility and versioning policy¶
Manifest version¶
The "manifest_version" integer is the primary compatibility signal for readers.
manifest_version |
Status |
Supported by |
|---|---|---|
1 |
Current |
This specification |
Future schemas increment manifest_version. A reader that does not recognise a manifest_version value must reject the package with a clear diagnostic (see error model) rather than silently ignoring unknown fields.
Forward compatibility within v1¶
New optional fields may be added to manifest v1 in minor typy releases. Readers encountering unknown fields must ignore them (be liberal in what they accept).
Removing or renaming required fields, or changing the type of any existing field, requires a new
manifest_version.
Package versioning¶
Package authors use Semantic Versioning for "version":
MAJOR – incompatible API or field changes in the template.
MINOR – new optional fields or backwards-compatible feature additions.
PATCH – bug fixes or asset updates that do not alter the template interface.
typy_compatibility¶
The "typy_compatibility" field uses PEP 440 version specifiers so that the installed typy version can be checked before importing a package.
Using a compatible-release specifier (~=) or an upper bound (<) is recommended when a package relies on behaviour introduced in a specific release.
Error model for invalid packages¶
Errors are reported as structured diagnostics. Each diagnostic has a code, a human-readable message, and an optional hint with a corrective action.
Diagnostic structure¶
{
"code": "PKG_E003",
"message": "manifest.json is missing required field: 'name'",
"hint": "Add a 'name' field using only lowercase letters, digits, and hyphens (e.g. 'my-template')."
}
Error codes¶
Code |
Trigger condition |
Example message |
|---|---|---|
|
File is not a valid ZIP archive |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A required field is absent |
|
|
A field has the wrong type |
|
|
|
|
|
|
|
|
|
|
|
A path inside the archive escapes the root ( |
|
|
|
|
|
Installed typy version does not satisfy |
|
Validators must collect all applicable errors before reporting, so that a user can fix all problems in one pass.
Example: invalid manifest — multiple errors¶
{
"manifest_version": 1,
"name": "My Template",
"version": "not-a-version",
"description": "A report template.",
"author": "Jane Doe",
"typy_compatibility": ">=0.1.0"
}
Expected diagnostics:
PKG_E008 'name' must match ^[a-z0-9][a-z0-9-]*[a-z0-9]$, got 'My Template'.
Hint: Use only lowercase letters, digits, and hyphens (e.g. 'my-template').
PKG_E009 'version' must be a valid semantic version (e.g. '1.0.0'), got 'not-a-version'.
Hint: Use MAJOR.MINOR.PATCH format as defined at https://semver.org.
PKG_E010 template.py not found in package root. The Template subclass must be defined in template.py.
Hint: Add a template.py file to the archive root that defines a subclass of typy.templates.Template.
Non-goals (MVP)¶
Implementing
typy package export/importcommands — tracked in a separate issue.A remote registry or marketplace for packages.
Package signing or tamper-detection.
Dependency resolution or a lock-file mechanism.
See also¶
Template reference — built-in templates and field schemas
CLI reference — available commands
Getting started — first-run walkthrough