{}OPF
DocsHow-to

Generate OPF decks with the Claude API

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

How it works

Claude's structured outputs constrain the response to a JSON Schema passed in output_config.format, so the model returns a deck that matches the schema's shape. Save the result as *.opf.json, validate it, and hand it to any OPF renderer.

Claude's structured outputs require additionalProperties: false on every object. Unlike OpenAI strict mode, optional properties stay optional — no nullable workarounds needed, which keeps the schema closer to plain OPF.

Output schema

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

claude-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",
            "description": "Optional slide subtitle."
          },
          "text": {
            "type": "string",
            "description": "Short body paragraph for the slide."
          },
          "items": {
            "type": "array",
            "description": "Bullet points or short takeaways.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "title"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "$schema",
    "name",
    "slides"
  ],
  "additionalProperties": false
}

Generate a deck

A minimal TypeScript example using the official Anthropic SDK:

generate-deck.ts
import Anthropic from "@anthropic-ai/sdk"
import opfDeckSchema from "./claude-opf.schema.json"

const anthropic = new Anthropic()

const response = await anthropic.messages.create({
  model: "claude-opus-4-8",
  max_tokens: 16000,
  output_config: {
    format: {
      type: "json_schema",
      schema: opfDeckSchema,
    },
  },
  messages: [
    {
      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.`,
    },
  ],
})

const block = response.content.find((b) => b.type === "text")
const deck = JSON.parse(block.text)

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.

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