OPF
DocsHow-to

Google AI Studio structured output

Use AI Studio structured outputs to make Gemini return OPF-shaped JSON that can be copied, validated, and rendered.

Steps

To generate a presentation with Gemini, paste the OPF starter schema below into Google AI Studio's structured output editor, run the prompt, and save the JSON response as deck.opf.json. Then validate it and convert it to PowerPoint or PDF with the OPF CLI, in a project with the CLI and export packages installed (first local run):

shell
npx opf validate deck.opf.json --fail-on warning
npx opf convert deck.opf.json deck.pptx
npx opf convert deck.opf.json deck.pdf

Checked on October 29, 2026 with OPF CLI 0.29.1: the narrative example below passes these commands and converts to PPTX and PDF, and a unit test in this site's CI checks it against the starter schema and the installed OPF package. The AI Studio steps themselves were not re-run for that check.

  1. Open Google AI Studio and choose a Gemini model that supports structured outputs.
  2. Open Structured outputs, switch to Code Editor, and paste the schema below.
  3. Save the structured output schema.
  4. Paste the prompt template into the main prompt field, replace the brief, and run it.
  5. Copy the JSON response into a *.opf.json file and validate it against the OPF schema.

Use the compact starter schema for this walkthrough. Consult the full reference for additional content and metadata fields.

Structured output schema

Paste this into AI Studio's structured output Code Editor. The copy button copies the full schema object.

google-ai-studio-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. Use the common single-audience OPF string form: a free-form description or an audiences catalog reference (an id such as executives, or name:id for a named catalog)."
    },
    "tone": {
      "type": "string",
      "description": "The tone of the deck, such as formal, executive, technical, educational, or sales."
    },
    "narrative": {
      "type": "string",
      "description": "A narrative catalog reference such as custom:retention-story, never an inline object. Embed a custom record under catalogs.custom.narratives, as in the complete example below."
    },
    "catalogs": {
      "type": "object",
      "description": "OPF catalog groups. A custom narrative record belongs under catalogs.custom.narratives, keyed by the id used in the narrative reference."
    },
    "design": {
      "type": "object",
      "description": "Portable design hints for an OPF renderer.",
      "properties": {
        "theme": {
          "type": "string",
          "description": "Theme identifier or descriptive theme name."
        },
        "colorScheme": {
          "type": "string",
          "description": "Color scheme identifier or descriptive color scheme name."
        },
        "fontScheme": {
          "type": "string",
          "description": "Font scheme identifier or descriptive font scheme name."
        },
        "dimensions": {
          "type": "string",
          "enum": [
            "widescreen",
            "standard"
          ],
          "description": "Deck aspect ratio."
        }
      }
    },
    "slides": {
      "type": "array",
      "minItems": 1,
      "description": "Ordered slides in the deck.",
      "items": {
        "type": "object",
        "properties": {
          "beat": {
            "type": "string",
            "description": "Optional beat id from the narrative record referenced by narrative (for example catalogs.custom.narratives['retention-story'].beats)."
          },
          "layout": {
            "type": "string",
            "description": "Registered layout id (starter subset).",
            "enum": [
              "cover",
              "section",
              "text",
              "list",
              "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"
        ]
      }
    }
  },
  "required": [
    "$schema",
    "name",
    "slides"
  ]
}

Optional narrative: reference the record

The narrative field names a catalog record. This complete portable example embeds its custom record; slide beats point to IDs inside that record, not to a narrative object on the deck. Catalog references.

narrative-example.opf.json
{
  "$schema": "https://openpresentation.org/schema/opf/v1",
  "name": "Retention update",
  "narrative": "custom:retention-story",
  "catalogs": {
    "custom": {
      "narratives": {
        "retention-story": {
          "name": "Retention story",
          "beats": [
            {
              "id": "evidence",
              "name": "Evidence"
            },
            {
              "id": "actions",
              "name": "Actions"
            }
          ]
        }
      }
    }
  },
  "slides": [
    {
      "title": "What changed",
      "beat": "evidence",
      "text": "Retention improved in the fictional pilot."
    },
    {
      "title": "What happens next",
      "beat": "actions",
      "text": "Review the pilot and choose the next action."
    }
  ]
}

Audience forms

OPF accepts the common single-audience case as a string. That string can be a free-form description, an audiences catalog reference: an id such as executives, or name:id for a record in a named catalog (references are never URLs). The existing non-empty array form remains valid for multiple audiences.

audience-forms.opf.json
{
  "singleFreeFormAudience": {
    "audience": "Biology Students and Wildlife Enthusiasts"
  },
  "singleCatalogAudience": {
    "audience": "executives"
  },
  "multipleAudiences": {
    "audience": [
      "board",
      {
        "id": "executives",
        "attentionBudgetMinutes": 20
      }
    ]
  }
}

Multiple audiences in AI Studio

The starter schema above asks AI Studio for the single-string form. If a deck must return multiple audiences with mixed string and object metadata, replace the audience property in the schema with this array-only property.

audience-property-array.json
{
  "type": "array",
  "minItems": 1,
  "description": "Multiple intended audiences. Each item is a free-form audience description, an audiences catalog reference, or an inline audience metadata object.",
  "items": {
    "oneOf": [
      {
        "type": "string",
        "description": "Free-form description or audiences catalog reference (id or name:id)."
      },
      {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Audience catalog reference (id or name:id), or a stable custom audience id."
          },
          "name": {
            "type": "string",
            "description": "Human-readable audience name or description."
          },
          "attentionBudgetMinutes": {
            "type": "integer",
            "description": "Optional audience attention budget in minutes."
          },
          "technicalFluency": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "description": "Optional technical fluency hint."
          },
          "decisionPower": {
            "type": "string",
            "description": "Optional decision-making role, such as decision-maker, advisory, or influencer."
          }
        },
        "required": [
          "id"
        ]
      }
    ]
  }
}

Prompt

Use this prompt with the structured output schema enabled.

prompt.txt
Create an Open Presentation Format (OPF) JSON deck for the brief below.

Follow the structured output schema exactly. Use the "$schema" value from the schema. Use "audience" as a single string unless you are using a multi-audience OPF schema. Prefer short slide titles, one main idea per slide, and either "text" or "items" on each content slide. If a narrative is useful, use a catalog reference string in "narrative" and embed its record under catalogs.custom.narratives. Use "beat" values matching that record's beats, as in the complete narrative example. Never put an inline object in "narrative".

Brief:
[Paste the topic, audience, desired slide count, source notes, and any must-include points here]

Example brief

brief.txt
Topic: A 10-minute board update on Q2 customer retention.
Audience: Board of Directors.
Slide count: 6.
Tone: Formal and concise.
Must include: retention trend, churn drivers, product adoption signals, renewal risks, and next-quarter actions.

Validate

AI Studio constrains the shape of the response, but OPF tooling should still validate the finished file before rendering. Compare the result with the OPF schema reference, or fetch the canonical schema at https://openpresentation.org/schema/opf/v1.

Google documents structured output support in the Gemini structured outputs guide.