Skip to content

Document Structure

Every Press document follows a consistent structure: a root element, a document definition containing pages, and optional sections for flows, styles, data, and assets. This guide covers how to set up the skeleton of your document and configure pages.

The <press> Root Element

All Press documents begin with <press> and end with </press>. This is the top-level container for everything in your template.

xml
<press>
  <!-- All other elements go here -->
</press>

Inside <press>, you can place the following top-level elements in any order:

  • <document> -- the schematic of how pages are structured to create the output PDF
  • <pages> -- reusable page definitions
  • <flows> -- variable sized content which breaks across pages
  • <styles> -- style rules and aliases
  • <data> -- changeable data used to modify parts of the document or create figures, tables, etc.
  • <assets> -- fonts, images, colors, and constant data
  • <components> -- reusable custom elements

The <document> Element

The <document> element defines the sequence of pages in your PDF. At a minimum, it contains <page> elements (either inline or references to named definitions) and controls the order they appear.

xml
<press>
  <document>
    <page width="21cm" height="29.7cm" page-margin="2cm">
      <h1>Quarterly Report</h1>
      <p>Prepared by Greenfield Analytics Ltd.</p>
    </page>
  </document>
</press>

Setting Defaults on <document>

You can set default attributes on <document> that all child pages will inherit. This avoids repeating the same dimensions and margins on every page.

xml
<press>
  <document width="21cm" height="29.7cm" page-margin="2cm">
    <page>
      <h1>Cover Page</h1>
    </page>
    <page>
      <h1>Chapter One</h1>
      <p>The story begins here...</p>
    </page>
  </document>
</press>

Both pages inherit the A4 dimensions and 2cm margin. Any page can override these defaults by specifying its own values:

xml
<document width="21cm" height="29.7cm" page-margin="2cm">
  <page>
    <p>This page uses the defaults (A4, 2cm margin).</p>
  </page>
  <page page-margin="1cm">
    <p>This page overrides the margin to 1cm.</p>
  </page>
</document>

Page Formats

Press supports standard paper sizes through the format attribute, so you do not need to remember exact dimensions.

xml
<page format="A4" page-margin="2cm">
  <p>Standard A4 page.</p>
</page>

The supported formats and their dimensions are:

FormatDimensions
A084.1cm x 118.9cm
A159.4cm x 84.1cm
A242cm x 59.4cm
A329.7cm x 42cm
A421cm x 29.7cm
A514.85cm x 21cm
A610.5cm x 14.85cm
A77.4cm x 10.5cm
A85.2cm x 7.4cm
A93.7cm x 5.2cm
A102.6cm x 3.7cm

Custom Dimensions

For non-standard page sizes, specify width and height directly. Values can be in points (pt) or centimetres (cm). PDFs use 72 points per inch.

xml
<!-- US Letter size -->
<page width="612pt" height="792pt" page-margin="72pt">
  <p>US Letter page in points.</p>
</page>

<!-- Custom square page -->
<page width="15cm" height="15cm" page-margin="1cm">
  <p>A square format, useful for social media or booklets.</p>
</page>

Landscape Orientation

Press has three methods of switching orientation:

xml
<!-- Landscape A4 - switched width and height values -->
<page width="29.7cm" height="21cm" />

<!-- Landscape A4 -->
<page format="A4" orientation="landscape" />

<!-- Also Landscape A4 -->
<page format="A4-landscape" />

Here is a complete example producing a landscape certificate:

xml
<press>
  <document>
    <page format="A4" orientation="landscape" page-margin="2cm">
      <frame v-align="center" h-align="center" width="100%" height="100%">
        <h1 text-align="center" font-size="36pt">Certificate of Completion</h1>
        <p text-align="center" font-size="18pt">Awarded to Jane Doe</p>
        <p text-align="center" font-size="14pt">For outstanding performance in Q3 2025</p>
        <p text-align="center" font-size="12pt" font-color="grey">
          Greenfield Analytics Ltd.
        </p>
      </frame>
    </page>
  </document>
</press>

Page Margins

The page-margin attribute sets uniform spacing around the content area. You can also control individual sides:

xml
<!-- Uniform margin -->
<page format="A4" page-margin="2cm">
  ...
</page>

<!-- Different margins per side -->
<page format="A4"
      page-margin-top="3cm"
      page-margin-bottom="2cm"
      page-margin-left="2.5cm"
      page-margin-right="2.5cm">
  ...
</page>

A page in Press is a special kind of frame, so you can also use padding instead of page-margin. However, page-margin is more intuitive when thinking about physical page layout.

Page Definitions with <pages>

When a page layout is used more than once, define it in the <pages> element and reference it by name from <document>. This keeps your document structure clean and avoids duplication.

xml
<press>
  <pages>
    <title-page>
      <frame v-align="center" h-align="center" width="100%" height="100%">
        <h1 text-align="center" font-size="fit">{{ data.title }}</h1>
        <p text-align="center" font-color="grey">{{ data.subtitle }}</p>
      </frame>
    </title-page>

    <body-page>
      <frame margin-bottom="0.5cm" font-color="grey" font-size="9pt">
        {{ data.title }}
      </frame>
      <flow name="body" />
    </body-page>
  </pages>

  <document format="A4" page-margin="2cm">
    <title-page />
    <body-page repeat="true" flow="body" />
  </document>

  <flows>
    <body>
      <h2>Introduction</h2>
      <p>This report examines trends in residential property values
        across the northern region over the past five years.</p>
    </body>
  </flows>

  <data>
    <title>Regional Property Market Analysis</title>
    <subtitle>Prepared by Northbrook Consulting Group</subtitle>
  </data>
</press>

The <pages> element can also specify default attributes, just like <document>:

xml
<pages format="A4" page-margin="2cm">
  <cover-page>
    ...
  </cover-page>
  <content-page>
    ...
  </content-page>
</pages>

Dynamic Page Selection from Data

When generating documents from data, you may need to switch between different page layouts. Use a data reference in the name attribute of a <page> tag to select the page definition dynamically.

xml
<press>
  <pages>
    <summary-page format="A4" page-margin="2cm">
      <h1>Summary</h1>
      <flow name="body" />
    </summary-page>

    <detail-page format="A4" page-margin="1.5cm">
      <h2>Detailed Findings</h2>
      <flow name="body" />
    </detail-page>
  </pages>

  <document>
    <repeat data="data.sections" item="section">
      <page name="{{ section.page-type }}" />
    </repeat>
  </document>

  <data type="json">
    {
      "sections": [
        { "page-type": "summary-page" },
        { "page-type": "detail-page" },
        { "page-type": "detail-page" },
        { "page-type": "summary-page" }
      ]
    }
  </data>
</press>

This produces four pages, alternating between the two layouts as the data dictates.

Required Flows

A page reference in <document> can specify required flows using the flow attribute. If any of the listed flows are empty, that page is skipped entirely.

xml
<document format="A4" page-margin="2cm">
  <cover-page />
  <appendix-page flow="appendix" />
  <body-page repeat="true" flow="body" />
</document>

In this example, appendix-page only appears if the appendix flow has content. The cover-page always appears, and body-page repeats until the body flow is exhausted.

Complete Example: Multi-Page Business Report

Here is a full document structure combining page definitions, defaults, and repeating pages:

xml
<press>
  <document width="21cm" height="29.7cm" page-margin="2cm">
    <cover-page />
    <repeat flow="body">
      <odd-page />
      <even-page />
    </repeat>
  </document>

  <pages>
    <cover-page page-margin="3cm">
      <frame v-align="center" width="100%" height="100%">
        <h1 font-size="fit">{{ data.report-title }}</h1>
        <frame height="1cm" />
        <p font-size="14pt" font-color="#555555">{{ data.company }}</p>
        <p font-size="12pt" font-color="#888888">{{ data.date }}</p>
      </frame>
    </cover-page>

    <odd-page flow="body">
      <frame direction="row" margin-bottom="0.5cm">
        <frame width="fill" font-size="9pt" font-color="grey">
          {{ data.report-title }}
        </frame>
        <frame font-size="9pt" font-color="grey" text-align="right">
          <page-number />
        </frame>
      </frame>
      <flow name="body" />
    </odd-page>

    <even-page flow="body">
      <frame direction="row" margin-bottom="0.5cm">
        <frame width="fill" font-size="9pt" font-color="grey">
          <page-number />
        </frame>
        <frame font-size="9pt" font-color="grey" text-align="right">
          {{ data.company }}
        </frame>
      </frame>
      <flow name="body" />
    </even-page>
  </pages>

  <flows>
    <body>
      <h2>Executive Summary</h2>
      <p>This report provides a comprehensive analysis of operational
        performance across all divisions for the fiscal year.</p>
      <h2>Financial Overview</h2>
      <p>Total revenue increased by 12% compared to the prior year,
        driven primarily by growth in the consulting division.</p>
    </body>
  </flows>

  <data>
    <report-title>Annual Operations Report</report-title>
    <company>Meridian Solutions Group</company>
    <date>January 2026</date>
  </data>
</press>

This produces a cover page followed by alternating odd/even body pages, each with its own header layout and automatic page numbering.