What Templates Are
A template is a .potx (or .pptx) file that contains slide masters, slide layouts, and a theme. When you pass a template Buffer on PaperDocument.template, the engine inherits the template's visual identity instead of building a blank presentation from scratch.
Templates provide:
- Slide masters: Background artwork, logos, footer placeholders
- Slide layouts: Named arrangements of placeholders (title, body, content, etc.)
- Theme: Color scheme, font scheme, and effect scheme
- Slide dimensions: Width and height parsed from
<p:sldSz>in the template'spresentation.xml
Using Templates in PaperDocument
Pass the template file as a Buffer on the document:
import { PaperEngine } from "@paperjsx/core/engine";
import { readFileSync } from "fs";
const template = readFileSync("brand-template.potx");
const doc = {
type: "Document" as const,
meta: { title: "Branded Deck" },
template,
slides: [
{
type: "Slide" as const,
layoutName: "Title Slide",
children: [
{
type: "Text",
placeholder: { type: "ctrTitle" },
content: "Q4 Business Review",
},
{
type: "Text",
placeholder: { type: "subTitle" },
content: "December 2025",
},
],
},
],
};
const pptx = await PaperEngine.render(doc);
Layout and Master References
Each PaperSlide can specify which layout and master to use:
interface PaperSlide {
layoutName?: string; // Name of the layout in the template (e.g., "Title Slide", "Two Content")
masterName?: string; // Name of the slide master (for multi-master templates)
// ...
}
If layoutName is omitted, the engine uses the first layout of the first master. If masterName is omitted but layoutName is provided, the engine searches all masters for a matching layout.
Placeholder Injection
When using templates, nodes can target specific placeholders in the layout via the placeholder field:
interface PlaceholderRef {
type?: PlaceholderType; // "ctrTitle", "subTitle", "body", "dt", "sldNum", etc.
idx?: number; // Placeholder index from the layout XML
}
OOXML placeholder types (from ECMA-376): body, chart, clipArt, ctrTitle, dgm, dt, ftr, hdr, media, obj, pic, sldImg, sldNum, subTitle, tbl, title.
The engine parses each layout's placeholders (position, size, text styles) and injects your content into the matching placeholder shape. This preserves the template's exact positioning and font formatting.
Template Parsing
Internally, the engine calls parseTemplate() to index the template:
interface TemplateIndex {
theme: ThemeData;
layouts: LayoutInfo[];
slideMasters: SlideMasterInfo[];
themes: Array<{ data: ThemeData; xml: string }>;
slideWidth: number; // pixels, parsed from <p:sldSz>
slideHeight: number; // pixels
masterTextStyles: MasterTextStyles;
// ...archive internals
}
Each LayoutInfo includes the layout name, its placeholders (with x/y/width/height positions), and the index of its parent master.
Theme Resolution from Templates
When a template is present, the engine extracts the theme from the template's theme1.xml. If the PaperDocument also has a theme field, the two merge:
- Template theme provides the base color scheme and font scheme
- Document-level
theme.colorSchemeoverrides specific slots (e.g., replacingaccent1) - Document-level
theme.fontSchemeoverrides font selections
This allows you to use a corporate template but swap the accent color per client.
Template Preflight
The PaperEngine.preflight() method checks template compatibility before rendering:
const report = await PaperEngine.preflight(doc);
if (report.templateReport) {
console.log("Support level:", report.templateReport.templateSupportLevel);
console.log("Unsafe layouts:", report.templateReport.unsafeLayouts);
console.log("Placeholder coverage:", report.templateReport.placeholderCoverage);
}
The TemplatePreflightReport contains:
| Field | Type | Description |
|---|---|---|
templateSupportLevel | `"certified" | "supported" |
unsafeLayouts | string[] | Layout names that cannot be reliably populated |
placeholderCoverage | number (0-1) | Fraction of layout placeholders matched by slides |
expectedFallbackRisk | `"low" | "medium" |
missingPlaceholderCount | number | Count of required placeholders with no content |
If templateSupportLevel is "unsafe", the render throws COMPATIBILITY_CONTRACT_VIOLATION.
Hosted API: Brand Packs
On the hosted V2 API, templates are managed as "brand packs" that you upload through the dashboard. Reference them in a PresentationSpec via brand:
{
"version": "2.0",
"title": "Client Deck",
"brand": { "brandPackId": "bp_abc123" },
"slides": [
{ "slideType": "title-body", "title": "Overview", "body": ["Key points here"] }
]
}
The API resolves the brand pack to a template buffer, applies layout mapping, and runs the full render pipeline.
Limitations
- Templates must be valid
.potxor.pptxfiles; corrupt archives fail at parse time - The engine does not modify existing slides in the template -- it only appends new slides using the template's layouts and masters
- Slide masters with complex animations or embedded macros are preserved but not interpreted
- Maximum uncompressed template size is enforced to prevent memory exhaustion