{}OPF
DocsReferenceView source

Content Payloads

Slide content lives directly on a slide as a full-slide payload, in layout-agnostic blocks, or inside a promoted region key such as left, center+right, or top:left.

The optional payload type can make intent explicit, but OPF should usually infer the content kind from the field present:

FieldInferred typeNotes
texttextPlain string or TextRun[].
bulletstextSimple text bullets, usually string[].
itemslistGeneric list payload, usually string[] or ListItem[].
imageimageAsset string shorthand or Asset object with src and optional metadata.
videovideoAsset string shorthand or Asset object with src and optional metadata.
chartchartChart object with type and tabular data.
tabletableTable object with optional columns and required rows.
codecodeString shorthand or Code object with source, language, and filename.
metricmetricString/number shorthand or Metric object with value, label, description, unit, delta, and trend.
quotequoteString shorthand or Quote object with text, attribution, and source.
timelinetimelineArray shorthand or Timeline object with name, description, and events.

Blocks

Use slide-level blocks when a slide contains multiple content payloads, but exact placement should be inferred by the renderer. Blocks may contain a concrete content payload or a nested group with its own blocks and optional composition. Groups cannot mix child blocks with leaf payload fields. See dynamic composition for nesting and inheritance rules.

json
{
  "title": "Customer Feedback Summary",
  "blocks": [
    {
      "table": {
        "columns": ["Theme", "Mentions"],
        "rows": [
          ["Speed", 42],
          ["Ease of use", 31]
        ]
      }
    },
    {
      "quote": {
        "text": "The new workflow cut review time in half.",
        "attribution": "Operations Lead",
        "source": "Customer interview"
      }
    }
  ]
}

At slide root only, multiple content payload kinds are accepted as shorthand for the equivalent blocks form when there is no explicit type, no blocks, and no promoted region keys:

json
{
  "title": "Habitat & Territory",
  "text": "Jaguars are strongly associated with presence of water and dense cover.",
  "items": [
    "Primary habitats include dense rainforests, swamps, and seasonally flooded wetlands.",
    "Solitary animals that establish and defend large territories."
  ]
}

The same shorthand works for other content kinds:

json
{
  "title": "Evidence Snapshot",
  "chart": {
    "type": "line",
    "data": {
      "columns": ["Quarter", "Sightings"],
      "rows": [
        ["Q1", 12],
        ["Q2", 18]
      ]
    }
  },
  "quote": {
    "text": "Jaguar conservation depends on connected habitat.",
    "attribution": "Field researcher"
  }
}

Chart

Chart-specific fields are grouped under chart. Do not put loose chart data directly on a slide or region.

json
{
  "title": "Revenue Trend",
  "chart": {
    "type": "line",
    "data": {
      "columns": ["Quarter", "Revenue", "Costs"],
      "rows": [
        ["Q1", 12, 8],
        ["Q2", 18, 11],
        ["Q3", 24, 15]
      ]
    }
  }
}

Inline chart data is tabular by default. Renderers convert columns and rows into series, axes, legends, and workbook data internally.

Asset-backed data is still table-oriented:

json
{
  "chart": {
    "type": "column",
    "data": {
      "src": "asset:revenue-csv",
      "columns": ["Quarter", "Revenue"]
    }
  }
}

Table

Table-specific fields are grouped under table. Do not put loose columns or rows directly on a slide or region.

json
{
  "title": "Pipeline",
  "table": {
    "columns": ["Stage", "Count", "Value"],
    "rows": [
      ["Qualified", 42, "$1.2M"],
      ["Proposal", 18, "$840K"]
    ]
  }
}

Table body cells accept strings, numbers, booleans, or null. Since core 0.5.0, a cell or column header also accepts the same TextRun[] used by rich text:

json
{
  "table": {
    "columns": [["Quarter ", {"text": "growth", "bold": true}], "Value"],
    "rows": [
      [["Up ", {"text": "12%", "color": "#008800"}], 12]
    ]
  }
}

Use core 0.6.0, renderer 0.4.0, editor 0.3.0 and PPTX 0.4.0 together. Core measures run styles when checking overflow and keeps each row intact when paginating. The renderer traces rich cells for the editor's existing formatting, typing and undo controls; the exporter emits editable native text runs. PPTX 0.4.0 imports supported native character styles, paragraph defaults, theme fonts/colors, external links and significant whitespace as rich runs. Unstyled body cells remain strings, and cached display text cannot recover original scalar types or live fields. Conditional table styles, merged geometry and cell fills/borders/alignment remain limited; native PowerPoint visual parity is not yet verified.

Core 0.6.0 adds layoutTable from @openpresentation/opf/composition. It measures scalar and rich cells, keeps short rows compact, and gives wrapped or multiline rows the height they need. When space is constrained it reduces spare row height before shrinking text, and reports overflow when the minimum fitting size cannot fit. Pass the same scale, font family, measurement provider and effective minFontSize to each consumer. The returned row boxes, cell text boxes and fits are shared by the coordinated SVG and PPTX implementations; rich table cells use uniform line advances to match native cell paragraph spacing. Native viewer fidelity remains a separate verification boundary.

Code

Code-specific fields are grouped under code. A string value is shorthand for code.source; use object form when syntax highlighting or a file label matters. In object form, source is required.

json
{
  "title": "Decision Rule",
  "code": {
    "source": "if risk > threshold:\n    escalate(owner)\nelse:\n    approve(change)",
    "language": "python",
    "filename": "decision.py"
  }
}

Metric

Metric-specific fields are grouped under metric. A string or number value is shorthand for metric.value; numeric values stay numeric and are formatted by renderers at display time. Use object form when labels, descriptions, units, deltas, or trends matter.

json
{
  "title": "Operating Metric",
  "metric": {
    "value": "42%",
    "label": "Review cycle reduction",
    "description": "Median reduction across customer review workflows.",
    "delta": "+11 pts",
    "trend": "up"
  }
}

Quote

Quote-specific fields are grouped under quote. A string value is shorthand for quote.text; use object form when attribution or citation matters.

json
{
  "title": "Customer Proof",
  "quote": {
    "text": "The new workflow made exceptions visible before they became escalations.",
    "attribution": "VP Operations, Acme Corp",
    "source": "Customer interview"
  }
}

Timeline

Timeline-specific fields are grouped under timeline. An array value is shorthand for timeline.events; use object form when the timeline needs a name or description. Timeline events use when, what, and description.

json
{
  "title": "Rollout Plan",
  "timeline": {
    "name": "Regional Rollout",
    "description": "Major milestones for the rollout.",
    "events": [
      {
        "when": "Q1",
        "what": "Pilot",
        "description": "Launch with one operations team."
      },
      {
        "when": "Q2",
        "what": "Rollout",
        "description": "Expand to all regions."
      }
    ]
  }
}

Regions

Region keys address a 3×3 grid of rows (top, middle, bottom) and columns (left, center, right):

text
left                 center                 right
         +--------------------+--------------------+--------------------+
   top   |  top:left          |  top:center        |  top:right         |
         +--------------------+--------------------+--------------------+
  middle |  middle:left       |  middle:center     |  middle:right      |
         +--------------------+--------------------+--------------------+
  bottom |  bottom:left       |  bottom:center     |  bottom:right      |
         +--------------------+--------------------+--------------------+
  • A bare column key (left) spans all three rows; a bare row key (top) spans all three columns.
  • + spans adjacent rows or columns: center+right, top+middle.
  • row:column combines the two: top:left, middle+bottom:center+right.
  • Keys on one slide must not overlap, and regions cannot be mixed with root payload fields.

Spans compose into common slide shapes:

text
"left" + "center+right"             "top" + "middle+bottom"
  (sidebar + main)                    (headline band + body)
  +----------+------------------+     +-------------------------------+
  |          |                  |     |              top              |
  |          |                  |     +-------------------------------+
  |   left   |  center+right    |     |                               |
  |          |                  |     |         middle+bottom         |
  |          |                  |     |                               |
  +----------+------------------+     +-------------------------------+

  "top" + "middle+bottom:left" + "middle+bottom:center+right"
  (headline band, then sidebar + main)
  +---------------------------------------------+
  |                     top                     |
  +---------------+-----------------------------+
  |               |                             |
  | middle+bottom | middle+bottom:center+right  |
  | :left         |                             |
  |               |                             |
  +---------------+-----------------------------+

The same payload objects work inside regions — here, the sidebar-plus-main shape:

json
{
  "title": "Operating Snapshot",
  "left": {
    "table": {
      "columns": ["Metric", "Value"],
      "rows": [
        ["Revenue", "$4.2M"],
        ["Gross margin", "68%"]
      ]
    }
  },
  "center+right": {
    "chart": {
      "type": "line",
      "data": {
        "columns": ["Month", "Revenue"],
        "rows": [
          ["Jan", 3.4],
          ["Feb", 3.8],
          ["Mar", 4.2]
        ]
      }
    }
  }
}