Outline Schema
This document describes the JSON shape of the outline object produced by the course structure pipeline and emitted by the outline-generation workflow before it is merged into the full course record.
This version covers the persisted outline shape, including localized titles and the format-specific payload fields that appear on sections after localization and section generation.
The outline is a nested object with this shape:
modules → topics → sections
For the full course object that contains this outline under course.outline, see
Course Schema.
JSON Schema
The schema below mirrors the workflow export in
workflows/course/outline-generation/outline-generation.raw.yml, but expands it to
include the localization fields and the section payloads used by downstream
production workflows.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://fraya.local/schemas/outline.schema.json",
"title": "Fraya Outline",
"type": "object",
"additionalProperties": false,
"required": ["modules"],
"properties": {
"modules": {
"type": "array",
"description": "List of course modules",
"minItems": 1,
"items": {
"$ref": "#/$defs/Module"
}
}
},
"$defs": {
"Module": {
"type": "object",
"additionalProperties": false,
"required": ["title", "topics", "summary", "position"],
"properties": {
"title": {
"type": "string",
"description": "Module title without numbering prefix"
},
"localized_title": {
"type": "string",
"description": "Localized module title"
},
"summary": {
"type": "string",
"description": "Module summary"
},
"position": {
"type": "string",
"description": "Module position, for example \"1\""
},
"topics": {
"type": "array",
"description": "List of topics inside the module",
"minItems": 1,
"items": {
"$ref": "#/$defs/Topic"
}
}
}
},
"Topic": {
"type": "object",
"additionalProperties": false,
"required": ["title", "position", "blueprint", "sections"],
"properties": {
"title": {
"type": "string",
"description": "Topic title without numbering prefix"
},
"localized_title": {
"type": "string",
"description": "Localized topic title"
},
"position": {
"type": "string",
"description": "Topic position in the form [module].[topic], for example \"1.3\""
},
"blueprint": {
"type": "string",
"description": "Topic blueprint"
},
"sections": {
"type": "array",
"description": "List of sections inside the topic",
"minItems": 1,
"items": {
"$ref": "#/$defs/Section"
}
}
}
},
"Section": {
"type": "object",
"additionalProperties": false,
"required": ["section_type", "title", "position", "blueprint", "format"],
"properties": {
"section_type": {
"type": "string",
"description": "Semantic section type"
},
"title": {
"type": "string",
"description": "Section title without numbering prefix"
},
"localized_title": {
"type": "string",
"description": "Localized section title, when present"
},
"section_title": {
"type": "string",
"description": "Localized section title used by localization workflows"
},
"position": {
"type": "string",
"description": "Section position in the form [module].[topic].[section], for example \"2.3.10\""
},
"blueprint": {
"type": "string",
"description": "Section blueprint"
},
"format": {
"type": "string",
"description": "Presentation format identifier"
},
"content": {
"type": "string",
"description": "HTML content or script text, depending on the format"
},
"content_rendered": {
"type": "string",
"description": "Rendered HTML with the media asset embedded"
},
"image_data": {
"$ref": "#/$defs/ImageData"
},
"video_data": {
"$ref": "#/$defs/VideoData"
},
"questions": {
"type": "array",
"description": "Question blocks for ChoiceQuestions sections",
"items": {
"$ref": "#/$defs/QuestionItem"
}
},
"correct_feedback_text": {
"type": "string",
"description": "Feedback shown when the full answer set is correct"
},
"incorrect_feedback_text": {
"type": "string",
"description": "Feedback shown when the answer set is incorrect"
},
"placeholders": {
"type": "array",
"description": "Blank placeholders for FillTheBlanks sections",
"items": {
"$ref": "#/$defs/FillPlaceholder"
}
},
"question_data": {
"$ref": "#/$defs/QuestionData"
},
"artifact_data": {
"$ref": "#/$defs/ArtifactData"
}
},
"oneOf": [
{
"properties": {
"format": {
"const": "Text"
}
},
"required": ["content"]
},
{
"properties": {
"format": {
"enum": ["VideoPresentation", "VideoTalkingHead", "VideoScenario"]
}
},
"required": ["content", "video_data"]
},
{
"properties": {
"format": {
"enum": [
"TextWithPhoto",
"TextWithIllustration",
"TextWithPortrait",
"TextWithDiagram"
]
}
},
"required": ["content", "content_rendered", "image_data"]
},
{
"properties": {
"format": {
"const": "ChoiceQuestions"
}
},
"required": ["questions"]
},
{
"properties": {
"format": {
"const": "FillTheBlanks"
}
},
"required": [
"content",
"correct_feedback_text",
"incorrect_feedback_text",
"placeholders"
]
},
{
"properties": {
"format": {
"const": "QuestionWithFeedback"
}
},
"required": ["content", "question_data"]
},
{
"properties": {
"format": {
"const": "Artifact"
}
},
"required": ["content", "artifact_data"]
}
]
},
"ImageData": {
"type": "object",
"additionalProperties": false,
"required": ["url"],
"properties": {
"prompt": {
"type": "string",
"description": "Optional image generation prompt"
},
"url": {
"type": "string",
"format": "uri",
"description": "Image URL"
}
}
},
"VideoData": {
"type": "object",
"additionalProperties": false,
"required": ["platform", "video_id"],
"properties": {
"platform": {
"type": "string",
"description": "Video platform identifier"
},
"video_id": {
"type": "string",
"description": "Platform video identifier"
}
}
},
"ArtifactData": {
"type": "object",
"additionalProperties": false,
"required": ["path"],
"properties": {
"path": {
"type": "string",
"description": "Artifact path"
}
}
},
"QuestionItem": {
"oneOf": [
{
"$ref": "#/$defs/SingleChoiceQuestion"
},
{
"$ref": "#/$defs/MultiChoiceQuestion"
}
]
},
"SingleChoiceQuestion": {
"type": "object",
"additionalProperties": false,
"required": ["type", "question", "possible_answers"],
"properties": {
"type": {
"type": "string",
"const": "SingleChoiceQuestion"
},
"question": {
"type": "string",
"description": "Question text"
},
"possible_answers": {
"type": "array",
"description": "Answer options",
"items": {
"$ref": "#/$defs/SingleChoiceAnswer"
}
}
}
},
"MultiChoiceQuestion": {
"type": "object",
"additionalProperties": false,
"required": [
"type",
"question",
"possible_answers",
"correct_feedback_text",
"incorrect_feedback_text"
],
"properties": {
"type": {
"type": "string",
"const": "MultiChoiceQuestion"
},
"question": {
"type": "string",
"description": "Question text"
},
"possible_answers": {
"type": "array",
"description": "Answer options",
"items": {
"$ref": "#/$defs/MultiChoiceAnswer"
}
},
"correct_feedback_text": {
"type": "string",
"description": "Feedback for correct multi-answer combinations"
},
"incorrect_feedback_text": {
"type": "string",
"description": "Feedback for incorrect multi-answer combinations"
}
}
},
"SingleChoiceAnswer": {
"type": "object",
"additionalProperties": false,
"required": ["text", "correct", "feedback_text"],
"properties": {
"text": {
"type": "string",
"description": "Answer option text"
},
"correct": {
"type": "boolean",
"description": "Whether the answer is correct"
},
"feedback_text": {
"type": "string",
"description": "Answer-specific feedback text"
}
}
},
"MultiChoiceAnswer": {
"type": "object",
"additionalProperties": false,
"required": ["text", "correct"],
"properties": {
"text": {
"type": "string",
"description": "Answer option text"
},
"correct": {
"type": "boolean",
"description": "Whether the answer is part of the correct set"
}
}
},
"FillPlaceholder": {
"type": "object",
"additionalProperties": false,
"required": ["index", "type", "options"],
"properties": {
"index": {
"type": "integer",
"description": "Placeholder index"
},
"type": {
"type": "string",
"enum": ["dropdown", "input"]
},
"options": {
"type": "array",
"description": "Answer options for the blank",
"items": {
"$ref": "#/$defs/FillOption"
}
}
}
},
"FillOption": {
"type": "object",
"additionalProperties": false,
"required": ["text", "correct"],
"properties": {
"text": {
"type": "string",
"description": "Option text"
},
"correct": {
"type": "boolean",
"description": "Whether the option is correct"
}
}
},
"QuestionData": {
"type": "object",
"additionalProperties": false,
"required": ["question", "criteria"],
"properties": {
"question": {
"type": "string",
"description": "Question text"
},
"criteria": {
"type": "string",
"description": "Evaluation criteria"
}
}
}
}
}
Structural Rules
modulesis required and must contain at least one module.- Each module must have
title,summary,position, andtopics. localized_titleis optional on modules and topics.- Each topic must have
title,position,blueprint, andsections. localized_titleandsection_titleare optional on sections.- Each section must have
section_type,title,position,blueprint, andformat. ChoiceQuestionssections usequestionswithSingleChoiceQuestionandMultiChoiceQuestionitems.FillTheBlankssections useplaceholdersplus the feedback fields shown above.QuestionWithFeedbacksections usequestion_data.questionandquestion_data.criteria.Artifactsections useartifact_data.path.additionalPropertiesisfalseat every object level.- Titles in the outline JSON are plain strings without numbering prefixes.
positionvalues are hierarchical strings and must preserve the source outline order.- The disabled
Questionformat is intentionally excluded from this active schema.
Related files
- Course schema
- Questions
- Outline pipeline
workflows/course/outline-generation/outline-generation.raw.yml