{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://agenticdecks.com/schemas/v1/deckrun-slide-format.json",
  "$comment": "© 2026 Agentic Decks. Publicly readable. Not open source. See https://agenticdecks.com/schemas for usage terms.",
  "title": "Deckrun slide format (GET /schema response)",
  "description": "Response shape for GET /schema when category=slide. Describes the Markdown format for presentation decks: layout tags, two-column, notes, timer, attributes, inline images. Layout and surface_syntax are primary hints, not exclusive (e.g. a title-content slide may contain images or code). Renderers may interpret according to output medium. Other categories (resume, patent, generic, book) use their own format schemas. Additional top-level properties are allowed for renderer-specific extensions; core fields are version, logical_schema, surface_syntax, example_markdown, api, license.",
  "version": "1.0.0",
  "x-extensible": true,
  "logical_schema": {
    "$ref": "https://agenticdecks.com/schemas/v1/deckrun-slide.json"
  },
  "surface_syntax": {
    "slide_separator": "---",
    "description": "Slides are separated by --- (three hyphens) on a line by itself.",
    "layout_tags": [
      "<!-- <title-slide /> -->",
      "<!-- <title-content-slide /> --> or <!-- <slide><layout>title-content</layout></slide> -->",
      "<!-- <section-header-slide /> -->",
      "<!-- <two-content-slide /> --> or <!-- <2-column-slide /> -->",
      "<!-- <title-only-slide /> -->",
      "<!-- <title-no-footer-slide /> --> or <!-- <slide><layout>title-no-footer</layout></slide> -->",
      "<!-- <footer-only-slide /> --> or <!-- <slide><layout>footer-only</layout></slide> -->",
      "<!-- <full-blank-slide /> --> or <!-- <slide><layout>full-blank</layout></slide> -->",
      "<!-- <blank-slide /> -->",
      "<!-- <content-with-caption-slide /> -->",
      "<!-- <slide><layout>default</layout></slide> --> for explicit default"
    ],
    "two_column": {
      "description": "For two-content layout: column markers split the body into left and right.",
      "left_side": "<!-- <left-side /> --> — place before left column content.",
      "right_side": "<!-- <right-side /> --> — place before right column content.",
      "end_special_format": "<!-- <end-special-format /> --> — optional; content after this is full-width below the columns."
    },
    "notes": "<!-- <slide-notes> --> ... <!-- </slide-notes> --> — presenter notes (excluded from PDF; used for notes output, audio narration, and video). A slide may have multiple notes blocks; each becomes an independent TTS narration segment narrated in sequence. Optional language attribute sets the BCP-47 narration language for that block: <!-- <slide-notes language=\"ta-IN\"> -->. Defaults to TtsConfig.default_language (en-US). Multiple blocks on the same slide may use different languages — this is the single-source-of-truth approach for multilingual narration. Localized text must be provided by the author; no automatic translation is performed. Google TTS auto-selects a voice for each language (configured voice when matching default, {language}-Standard-A otherwise).",
    "slide_timer": "<!-- <slide-timer>N</slide-timer> --> — N = minimum seconds on screen (video mode only).",
    "slide_tag_attributes": "In HTML comment <!-- <slide>...</slide> -->: <layout>, <class>, <left_class>, <right_class>, <image>, <background_img>, <body_background_img>, <left_image>, <right_image>, <left_background_img>, <right_background_img>, <video_src>, <youtube_url>, <video_audio_mode>, <video_start_secs>, <video_end_secs>, <video_duck_db>. All optional. <video_src> and <youtube_url> are mutually exclusive. Supported video_audio_mode values are source|notes|mix|mute (deployment may support only a subset).",
    "inline_images": "Markdown or HTML <img> with classes: img-left, img-right, img-center, img-full-width; sizing: img-small, img-medium, img-large. Inline <img> src paths follow the same resolution rules as slide_tag_attributes image paths — see image_paths.",
    "image_paths": {
      "summary": "Image paths in slide tag attributes (background_img, image, left_image, etc.) and inline <img src> are resolved in this order: (1) relative to the markdown file's directory (CLI) or assets map (API), (2) --assets-dir override if set, (3) theme branding.assets_dir. Absolute paths are not supported.",
      "supported_formats": [
        "images/foo.png — relative to markdown file directory (recommended)",
        "./images/foo.png — same as above; leading ./ is normalized before resolution"
      ],
      "not_supported": [
        "../foo.png or ../../foo.png — path traversal ('..') is rejected in all modes (security)",
        "/absolute/path/foo.png — absolute paths are rejected in all modes (security)",
        "https://example.com/foo.png — remote URLs are not fetched; pass-through only"
      ],
      "security_note": "Absolute paths and '..' traversal are blocked in both CLI and service modes. In service mode, the asset sandbox is a temp directory; any path escaping it is rejected at the write stage (assets map) and the read stage (image resolution). In CLI mode, use --assets-dir to set a higher-level base directory if images live outside the markdown's directory.",
      "best_practice": "Place images in an images/ subdirectory next to the markdown file and reference them as images/foo.png. This works in both CLI and API modes.",
      "cli": "The markdown file's parent directory is used automatically as the assets base. Use --assets-dir to override. No flag needed when images are next to the .md file.",
      "api": "Pass images as base64 in the assets map: { \"images/foo.png\": \"<base64>\" }. The map key must exactly match the path string used in the markdown (e.g. images/foo.png)."
    }
  },
  "example_markdown": "<!-- <title-slide /> -->\n\n# My Deck\n\nSubtitle or org name\n\n---\n\n<!-- <title-content-slide /> -->\n\n## First slide\n\n- Bullet one\n- Bullet two\n\n<!-- <slide-notes> -->\nSpeaker notes for TTS.\n<!-- </slide-notes> -->\n\n---\n\n<!-- <title-content-slide /> -->\n\n## Multilingual slide\n\nContent here.\n\n<!-- <slide-notes language=\"ta-IN\"> -->\nதமிழில் குரல் வழங்கல் (Tamil narration).\n<!-- </slide-notes> -->\n\n<!-- <slide-notes> -->\nEnglish summary follows the Tamil narration on this same slide.\n<!-- </slide-notes> -->\n\n---\n\n<!-- <two-content-slide /> -->\n\n## Two columns\n\n<!-- <left-side /> -->\nLeft content.\n\n<!-- <right-side /> -->\nRight content.\n\n---\n\n## Second slide\n\nContent here.",
  "api": {
    "generate_request_options": "POST /generate can include optional overrides: voice_override (provider_id?, credential_id?, options?), image_override (future), slide_language, notes_language, audio_language, translate (On/Off; default Off). Profile defaults apply when not overridden.",
    "providers_catalog": "GET /providers (or providers section in GET /schema) lists available providers per capability (voice, image). Each entry: provider_id, display name, plan, options, requires_credential. Exposes supported translation language pairs and TTS languages per provider."
  },
  "license": "Use of this schema is subject to Agentic Decks / Deckrun terms. The schema may not be used to replicate or build a competing service. See API terms and Acceptable Use Policy."
}
