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.
{
"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:
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:
// 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.