{}OPF
DocsHow-to

Generate OPF decks with the OpenAI API

Use OpenAI structured outputs to make a model return OPF-shaped JSON that validates against the canonical schema.

How it works

OpenAI's structured outputs constrain a model to a JSON Schema you provide, so the response is guaranteed to match the schema's shape. Give it an OPF-shaped schema and the model returns a deck you can save as *.opf.json, validate, and hand to any OPF renderer.

Strict mode has two requirements that differ from plain JSON Schema: every object needs additionalProperties: false, and every property must appear in required. Optional OPF fields are modeled as nullable instead, and stripped after generation.

Strict-mode schema

This is a compact starter schema adapted for strict mode, not the full OPF schema. Use the schema reference when you need more OPF fields such as narratives, design hints, or multi-audience metadata.

openai-opf.schema.json
{
  "type": "object",
  "description": "An Open Presentation Format deck. Generate one valid OPF JSON presentation document.",
  "properties": {
    "$schema": {
      "type": "string",
      "enum": [
        "https://openpresentation.org/schema/opf/v1"
      ],
      "description": "The OPF schema URL. Always use this exact value."
    },
    "name": {
      "type": "string",
      "description": "Short title for the presentation."
    },
    "audience": {
      "type": "string",
      "description": "The intended audience for the deck, as a free-form description or audiences catalog id."
    },
    "tone": {
      "type": "string",
      "description": "The tone of the deck, such as formal, executive, technical, educational, or sales."
    },
    "slides": {
      "type": "array",
      "description": "Ordered slides in the deck.",
      "items": {
        "type": "object",
        "properties": {
          "layout": {
            "type": "string",
            "description": "Renderer layout hint.",
            "enum": [
              "title",
              "title-subtitle",
              "section",
              "content",
              "bullets",
              "two-column",
              "quote",
              "closing"
            ]
          },
          "title": {
            "type": "string",
            "description": "Concise slide title."
          },
          "subtitle": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional slide subtitle. Use null when not needed."
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Short body paragraph for the slide. Use null when the slide uses items instead."
          },
          "items": {
            "type": [
              "array",
              "null"
            ],
            "description": "Bullet points or short takeaways. Use null when the slide uses text instead.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "layout",
          "title",
          "subtitle",
          "text",
          "items"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "$schema",
    "name",
    "audience",
    "tone",
    "slides"
  ],
  "additionalProperties": false
}

Generate a deck

A minimal TypeScript example using the official OpenAI SDK and the Responses API:

generate-deck.ts
import OpenAI from "openai"
import opfDeckSchema from "./openai-opf.schema.json"

const openai = new OpenAI()

const response = await openai.responses.create({
  // Any model that supports structured outputs.
  model: "gpt-5.1",
  input: [
    {
      role: "user",
      content: `Create an Open Presentation Format (OPF) JSON deck for this brief:

Topic: A 10-minute board update on Q2 customer retention.
Audience: Board of Directors.
Slide count: 6.
Tone: Formal and concise.`,
    },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "opf_deck",
      strict: true,
      schema: opfDeckSchema,
    },
  },
})

const deck = JSON.parse(response.output_text)

Because strict mode returns nulls for unused optional fields, remove them before validation:

strip-nulls.ts
// Strict mode requires every property, so unused fields come back as null.
// Drop them before validating against the canonical OPF schema.
const cleaned = JSON.parse(
  JSON.stringify(deck, (key, value) => (value === null ? undefined : value)),
)

Validate

Structured outputs guarantee the response matches your starter schema, but OPF tooling should still validate the finished file against the canonical schema at https://openpresentation.org/schema/opf/v1 before rendering. The validation guide shows how with Ajv and ajv-cli.

OpenAI documents schema requirements and supported models in the structured outputs guide.