LC-JSON Specification
Spec version: 1.1-rc.1 Last updated: 2026-07-22
This directory contains the LC-JSON (Learning Content JSON) specification for structured learning content, covering the complete hierarchy from Course structure down to individual Question types.
Implementing LC-JSON? See NORMATIVE.md for the conformance requirements (RFC 2119 keywords, producer/consumer roles, versioning rules, URL stability promises). This README is descriptive; NORMATIVE.md is authoritative. For terminology, see GLOSSARY.md.
Complete Coverage:
- Five artifact types sharing a common flat root format: three content documents (Course, QuestionSet, Glossary), a vocabulary document (SubjectCollection), and an arrangement document (CurriculumPack)
- Course Hierarchy (Course → Units → Lessons → Items)
- 5 Lesson Item Types (Content, Exercise, Quiz, ContentSequence, Signpost)
- 19 Question Types (12 fully implemented + schema-validated; 7 reserved for a future minor version)
- JSON Schemas (27) for validation — strictly enforced by the reference validator
- Minimal + detailed examples (35 files, all schema-clean)
Design Principles
LC-JSON is machine-validatable, but human-inspectable.
The documents are validated automatically against JSON Schema Draft 7, but they are also designed so that authored content remains visible in the file. A teacher, curriculum designer, or teacher-developer can recognize courses, units, lessons, items, questions, prompts, choices, answers, and feedback without proprietary tooling — opening a course .json in any text editor should be enough to inspect what the course actually contains.
Technical fields such as $schema, specVersion, and globalId exist to make documents portable across tools and stable across re-imports, but they should not bury the pedagogical content. Where this trade-off arises in spec evolution — naming, structure, ordering of fields — the spec favors the form that keeps pedagogical content recognizable.
This is a deliberate stance against formats whose meaning only emerges through tooling. It is offered without promise of zero technical fields, because portability requires some; the promise is that the pedagogical structure stays inspectable to the people who authored it.
Wire Format
LC-JSON uses a flat root with a documentType discriminator (no enclosing envelope around the document). Every conforming document carries $schema, documentType, and specVersion as root-level siblings. The course content itself is hierarchical — Course → Units → Lessons → Items → Questions — and reflects how teachers structure their material.
Five artifact types
| Artifact | documentType | Schema | Description |
|---|---|---|---|
| Course | "course" | course.schema.json | Hierarchical course (Units → Lessons → Items). The usual shape for a full course. |
| Question Set | "questionSet" | question-set.schema.json | Flat list of questions for question-bank exchange and packaged delivery — no hierarchy. |
| Glossary | "glossary" | glossary.schema.json | Flat list of terms — pronunciation, translations, examples, inflected forms. Study material that attaches to a course, unit, or lesson. |
| Subject Collection | "subjectCollection" | subject-collection.schema.json | A reusable classification vocabulary: the tags and learning objectives for one subject at one level, as a portable document. |
| Curriculum Pack | "curriculumPack" | curriculum-pack.schema.json | An arrangement: sequence, pacing, and assessment checkpoints referencing a Subject Collection plus content documents. |
Required root fields (all artifact types)
{
"$schema": "https://lc-json.org/1.1-rc.1/<artifact>.schema.json",
"documentType": "course", // or "questionSet", "glossary",
// "subjectCollection", "curriculumPack"
"specVersion": "1.1",
"title": "...",
...
}
The $schema URL serves as a stable, versioned identifier and is used
by integrated development environments (IDEs such as VS Code) for schema
autocomplete. specVersion is
forward-compatible across the 1.x series — conforming consumers MUST
accept any 1.x value and reject 2.x+ cleanly.
Reserved question types (targeted for 2027)
Seven question types are reserved in the polymorphic discriminator set but do not yet have per-type schemas — full authoring and consumer support is targeted for 2027:
association, hotspot, graphicGapMatch, graphicAssociate,
graphicOrder, fileUpload, mediaPromptedEssay
The 12 question types with full per-type schemas — simpleGapFill,
trueFalseQuestion, multipleChoice, wordBankCloze, multiGapCloze,
multipleChoiceCloze, shortAnswer, essay, sentenceTransformation,
matching, ordering, placement — are the spec’s stable surface as of 1.0.
Consumer obligations for reserved (and unknown) types are normative under NORMATIVE.md §6: consumers MUST preserve them verbatim across read/write cycles, MUST NOT silently drop them, MUST treat their earned points as zero, and SHOULD render a non-interactive placeholder. The intent is round-trip preservation: a teacher exporting from a consumer that does not support hotspot can take the file back to a consumer that does, without losing the question. Producers SHOULD NOT emit reserved types in 1.0 documents intended for cross-implementation distribution; reserved types are tool-specific extensions until promoted.
Discriminator casing
Conforming producers emit camelCase question discriminators
(simpleGapFill, multipleChoice, etc.). All examples in this
directory strictly validate against the schemas in their canonical
casing. Non-canonical casings are non-conforming; consumers MUST
reject them.
What v1.1 adds — vocabularies, arrangements, and glossaries
LC-JSON 1.0 moved content: courses and question sets that survive the trip between tools. Version 1.1 adds the documents that sit around content — the classification it is organized by, the plan it is taught on, and the vocabulary students study alongside it. All three are ordinary LC-JSON files: flat root, stable ids, readable in a text editor.
A Subject Collection is a curriculum’s working vocabulary as a file. It holds the
tags and learning objectives for one scope — B2 adult general English, KS3
mathematics — with two properties free-text tagging cannot offer. First, every tag and
objective has a permanent id, so two courses classified with the same member are
comparably classified: search, curriculum mapping, and progress reporting can line
them up without guessing that “conditionals” and “if-clauses” mean the same thing.
Second, a collection can state precisely what external framework it tracks
(externalAlignments — a national curriculum section, an official training catalog
entry, an exam specification) without re-publishing that framework’s content. For an
educational authority or awarding body, this is the piece that makes publishing an
official vocabulary practical: author the objectives once, point at the official
register, and let any number of course authors reference the same members rather than
re-typing them. For a content author, it means the expensive work — writing good can-do
objectives — is done once per scope and reused, and a course built against a collection
says so in a form other tools can verify. See
subject-collection-reference.md.
A Curriculum Pack is a scheme of work that a machine can check. Where a collection
says what the objectives are, a pack says how a program covers them: an ordered
sequence of steps on a calendar-relative timeline (year / term / week — never real
dates, so any institution’s calendar fits), each step teaching, revisiting, or assessing
listed objectives, with pacing capacity and assessment checkpoints declared in the
document. Because steps reference objective ids rather than prose, a validator can
verify the claims a scheme of work usually only implies: nothing is assessed before it
is taught, spaced revisits actually have spacing, term plans fit term capacity, and —
against the referenced collection — every in-scope objective is taught and assessed at
least once (coverage, a declared contract with explicit exemptions). A pack can start
as a blueprint (the plan alone, every content slot empty), grow into a working
manifest as courses are bound, and ship as a self-contained bundle — one
document type at three depths of completion. For curriculum leads and inspectors, the
pack is the difference between “the scheme of work says so” and “any conforming
curriculum-pack validator holding the referenced collection can re-verify the claim.” See
curriculum-pack-reference.md.
A Glossary is the vocabulary students study, as a portable document. Terms with
pronunciation (IPA, a friendly respelling, audio), translations, example sentences, and
inflected forms — designed language-education-first but serving any subject’s key
words. A glossary attaches to a course, unit, or lesson (glossaryRefs), and consumers
can auto-link its terms in content, render study lists, or drive flashcards. It is the
one v1.1 type that is content rather than structure: where a collection classifies
what courses teach, a glossary is learning material. See
glossary-reference.md.
The three documents compose: a collection scopes a pack; the pack sequences courses,
question sets, and glossaries; every reference is by stable id, so the set travels
between tools without losing its joins. Consumers adopt at any depth — a tool that only
reads courses ignores the rest and loses nothing (NORMATIVE.md §5.1
scopes conformance per artifact type).
Directory Structure
specification/
├── README.md # This file
├── NORMATIVE.md # RFC 2119 conformance requirements (authoritative)
├── HTML_SAFETY.md # Normative HTML allowlist + sanitization profile
├── ACCESSIBILITY.md # Producer/consumer accessibility profile
├── LOCALIZATION.md # Language model: language / lang / supportLanguage; BCP 47; pronunciation
├── VALIDATION.md # Rule catalog — schema / validator / advisory tiers
├── ITEM_PATTERNS.md # Informative authoring guide
├── question-types-reference.md # Complete reference for all 19 question types
├── subject-collection-reference.md # Complete reference for the SubjectCollection type
├── curriculum-pack-reference.md # Complete reference for the CurriculumPack type
├── glossary-reference.md # Complete reference for the Glossary type
├── GLOSSARY.md # Terminology
├── schemas/ # JSON Schema validation files
│ ├── course.schema.json # Course (top level)
│ ├── question-set.schema.json # QuestionSet (flat artifact)
│ ├── glossary.schema.json # Glossary (flat artifact)
│ ├── subject-collection.schema.json # SubjectCollection (vocabulary artifact)
│ ├── curriculum-pack.schema.json # CurriculumPack (arrangement artifact)
│ ├── publication-fields.schema.json # Shared publication field group (§4.11)
│ ├── unit.schema.json # Unit (within Course)
│ ├── lesson.schema.json # Lesson (within Unit)
│ ├── item-base.schema.json # Base schema for all Items
│ ├── content-item.schema.json # ContentItem type
│ ├── exercise-item.schema.json # ExerciseItem type
│ ├── quiz-item.schema.json # QuizItem type
│ ├── content-sequence-item.schema.json # ContentSequenceItem type
│ ├── signpost-item.schema.json # SignpostItem type (intro/summary navigation)
│ ├── question-base.schema.json # Base schema for all Questions
│ ├── simple-gap-fill.schema.json # SimpleGapFill validation
│ ├── true-false-question.schema.json # TrueFalseQuestion validation
│ ├── multiple-choice.schema.json # MultipleChoice validation
│ ├── word-bank-cloze.schema.json # WordBankCloze validation
│ ├── multi-gap-cloze.schema.json # MultiGapCloze validation
│ ├── multiple-choice-cloze.schema.json # MultipleChoiceCloze validation
│ ├── short-answer.schema.json # ShortAnswer validation
│ ├── essay.schema.json # Essay validation
│ ├── sentence-transformation.schema.json # SentenceTransformation validation
│ ├── matching.schema.json # Matching validation
│ ├── ordering.schema.json # Ordering validation
│ └── placement.schema.json # Placement type validation
└── examples/ # Example JSON files (35 total)
├── course-minimal.json # Minimal Course example
├── question-set-minimal.json # Minimal QuestionSet example
├── glossary-minimal.json # Minimal Glossary example
├── subject-collection-minimal.json # Minimal SubjectCollection example
├── curriculum-pack-manifest.json # Minimal CurriculumPack example (manifest depth)
├── question-set-10-true-false.json # Richer QuestionSet showcase
├── unit-minimal.json # Minimal Unit example
├── lesson-minimal.json # Minimal Lesson example
├── 10-content-item.json # ContentItem with HTML
├── 11-exercise-item.json # ExerciseItem (graded homework example)
├── 12a-graded-quiz-item.json # QuizItem, isGraded:true (typical assessment)
├── 12b-ungraded-quiz-item.json # QuizItem, isGraded:false (diagnostic pre-test)
├── 13-content-sequence-item.json # ContentSequenceItem
├── 14-signpost-item.json # SignpostItem
├── 01-simple-gap-fill.json # Per-question examples (01-09)
├── ... # 09-sentence-transformation.json
├── 15-matching.json # Matching example
├── 16-ordering.json # Ordering example (word-level)
├── 16b-sentence-ordering.json # Ordering example (sentence-level — process narrative)
├── 16c-paragraph-ordering.json # Ordering example (paragraph-level — essay structure)
├── 17a-sentence-placement.json # Placement example (sentence-mode — Cambridge B2 First Part 6 style)
├── 17b-paragraph-placement.json # Placement example (paragraph-mode — IELTS Reading Matching Information style)
├── 17c-section-label-placement.json # Placement example (sectionLabel-mode — IELTS Matching Headings)
├── 17d-toefl-insertion-placement.json # Placement example (TOEFL Sentence Insertion — decoy-gaps variant)
└── sample-course-with-questions.json # Full course example
Total: 27 schemas (7 root/structural [course, questionSet, glossary, subjectCollection, curriculumPack, unit, lesson] + 1 publication-fields group + 1 item-base + 5 item types + 1 question-base + 12 question types).
Source layout vs. published layout. The tree above is the source directory, where the schemas sit in a single flat
schemas/. The published specification does not use that layout: it serves each publication from its own versioned directory, so the files appear asschemas/ ├── 1.1-rc.1/ # the current publication — 27 schemas ├── 1.0/ # frozen final release ├── 1.0-rc.1/ # frozen release candidates ├── 1.0-rc.2/ └── 1.0-rc.3/and each schema is served at an immutable versioned URL —
https://lc-json.org/1.1-rc.1/<name>.schema.jsonfor the current publication, with the frozen/1.0/and/1.0-rc.N/publications alongside it forever (NORMATIVE §8.3). That versioned URL is the value every document’s$schemafield carries, and it is the only citable form.This is why schema links differ between the two: the source documents use a relative
schemas/<name>.schema.jsonso contributors browsing the source tree can follow them, and the publication step rewrites every one of those links to its absolute versioned URL. A published schema link is always immutable — there is deliberately no mutable “current” alias to cite by mistake.
Course Hierarchy
A Course document has the following nested structure:
Course (top level)
└─ Units[] (array of units)
└─ Lessons[] (array of lessons)
└─ Items[] (array of items - 5 types)
├─ ContentItem (reading/content pages)
├─ ExerciseItem (questions; structural form, grading via isGraded)
├─ QuizItem (questions; structural form, grading via isGraded)
├─ ContentSequenceItem (grouped content)
└─ SignpostItem (intro/summary with objectives)
└─ Questions[] (only for ExerciseItem and QuizItem)
Minimal Examples for Quick Reference:
- course-minimal.json - Bare minimum Course structure
- unit-minimal.json - Bare minimum Unit
- lesson-minimal.json - Bare minimum Lesson
Lesson Item Types
Every Lesson contains an items array with one or more of these 5 item types:
| Item Type | Schema | Example | Description |
|---|---|---|---|
| ContentItem | content-item.schema.json | 10-content-item.json | Reading/content pages with HTML content (subject to HTML_SAFETY.md) |
| ExerciseItem | exercise-item.schema.json | 11-exercise-item.json | Exercise-shaped questions container. Grading independent (isGraded). |
| QuizItem (graded) | quiz-item.schema.json | 12a-graded-quiz-item.json | Quiz-shaped, isGraded: true — typical assessment. |
| QuizItem (ungraded) | quiz-item.schema.json | 12b-ungraded-quiz-item.json | Quiz-shaped, isGraded: false — diagnostic pre-test, self-check. Same schema, different policy. |
| ContentSequenceItem | content-sequence-item.schema.json | 13-content-sequence-item.json | Grouped content with layout options (carousel, tabs, accordion) |
| SignpostItem | signpost-item.schema.json | 14-signpost-item.json | Structural navigation (intro/summary) with objectives and stats; customHtml subject to HTML_SAFETY.md |
Exercise vs. Quiz. These are structural distinctions only. They render differently in the UI and contribute to separate point buckets (enabling weighted grading). Whether the score counts toward a learner’s grade is the
isGradedflag, set independently. The examples model this:11-exercise-item.jsonis a graded homework exercise (isGraded: true);12a-graded-quiz-item.jsonand12b-ungraded-quiz-item.jsonuse the same content under the same schema to show that quiz can be either graded or ungraded. The fourth combination (ungraded exercise / open practice) is conventional and not given its own example.For an authoring guide that walks through the full design space of
type×isGraded×isOptional×passMarkPercent— common patterns (graded homework, diagnostic pre-test, exit ticket, etc.) and how different consumers may interpret each combination — seeITEM_PATTERNS.md.
Key Properties (all items inherit from item-base.schema.json):
type(required) - Discriminator: “content”, “exercise”, “quiz”, “contentsequence”, or “signpost”title(required) - Display title for the itemsequence- Display order within lesson (0-based)instructions- Instructions shown to learnersuggestedTime- Estimated time in minutesisOptional- Whether item can be skipped
Questions Array:
- Only ExerciseItem and QuizItem have a
questionsarray - ContentItem, ContentSequenceItem, and SignpostItem do NOT contain questions
SignpostItem Properties:
signpostType(required) - “intro” or “summary”scope(required) - “course”, “unit”, or “lesson”customHtml(optional) - Custom HTML content to override auto-generated message
Documentation Files
1. question-types-reference.md
Complete JSON Format Reference
- All 19 Question Types with detailed specifications
- Property tables showing required/optional fields
- Examples for each question type
- Validation rules and best practices
- Common properties inherited by all questions
- Complete course example showing nested structure
When to use:
- Creating new course JSON files
- Understanding question type requirements
- Troubleshooting import errors
1b. Artifact type references
Complete JSON Format References for the v1.1 artifact types
- subject-collection-reference.md — SubjectCollection: scope, members (tags and objectives),
externalAlignments, carried copies in course documents. - curriculum-pack-reference.md — CurriculumPack:
sequence[]steps on the calendar-relative timeline, pacing, assessment checkpoints, thecoveragecontract, and the blueprint / manifest / bundle depths. - glossary-reference.md — Glossary: terms, pronunciation, the declared
translationLanguagesinventory,definitionTranslations,firstMention, andglossaryRefsattachment.
When to use:
- Authoring or consuming a collection, pack, or glossary document
- Understanding how the v1.1 types reference each other by stable id
2. JSON Schema Files (schemas/)
Machine-Readable Validation
JSON Schema files for automated validation using tools like ajv, jsonschema, or IDE validators.
Root Artifact Schemas:
course.schema.json- Course (top level)question-set.schema.json- QuestionSet (flat artifact)glossary.schema.json- Glossary (flat artifact)subject-collection.schema.json- SubjectCollection (vocabulary artifact)curriculum-pack.schema.json- CurriculumPack (arrangement artifact)publication-fields.schema.json- Shared publication field group, composed viaallOf(NORMATIVE §4.11)
Course Hierarchy Schemas:
unit.schema.json- Unit (within Course)lesson.schema.json- Lesson (within Unit)
Item Type Schemas:
item-base.schema.json- Base schema for all Itemscontent-item.schema.json- ContentItem typeexercise-item.schema.json- ExerciseItem typequiz-item.schema.json- QuizItem typecontent-sequence-item.schema.json- ContentSequenceItem typesignpost-item.schema.json- SignpostItem type (intro/summary navigation)
Question Type Schemas:
question-base.schema.json- Base properties for all questionssimple-gap-fill.schema.json- SimpleGapFill type validationtrue-false-question.schema.json- TrueFalseQuestion type validationmultiple-choice.schema.json- MultipleChoice type validationword-bank-cloze.schema.json- WordBankCloze type validationmulti-gap-cloze.schema.json- MultiGapCloze type validationmultiple-choice-cloze.schema.json- MultipleChoiceCloze type validationshort-answer.schema.json- ShortAnswer type validationessay.schema.json- Essay type validationsentence-transformation.schema.json- SentenceTransformation type validationmatching.schema.json- Matching type validationordering.schema.json- Ordering type validationplacement.schema.json- Placement type validation
Strict enforcement: the reference validator (validate_course.py) runs every document through these schemas as a primary pass via the jsonschema package (≥4.18, modern referencing Registry API). Per-question type-specific dispatch keys off the type discriminator. Install dependencies with pip install -r tools/requirements.txt.
Usage Example (Node.js with ajv):
const Ajv = require('ajv');
const ajv = new Ajv();
const baseSchema = require('./schemas/question-base.schema.json');
const simpleGapFillSchema = require('./schemas/simple-gap-fill.schema.json');
const validate = ajv.compile(simpleGapFillSchema);
const valid = validate(questionData);
if (!valid) {
console.error(validate.errors);
}
3. Example Files (examples/)
Ready-to-Use Templates
Minimal Hierarchy Examples - Quick Format Reference
Ultra-minimal examples for quick consultation when creating courses:
- course-minimal.json - Bare minimum Course structure with required properties
- unit-minimal.json - Minimal Unit within a course
- lesson-minimal.json - Minimal Lesson within a unit
Use these as exact-format references (e.g., a unit on Travel + present perfect).
Item Type Examples (10-13) - Item Structure Reference
Individual examples for each of the Lesson Item types:
- 10-content-item.json — ContentItem with rich HTML content (Declaration of Independence reading)
- 11-exercise-item.json — ExerciseItem framed as graded homework (5 T/F world-rivers questions;
isGraded: true) - 12a-graded-quiz-item.json — QuizItem as a graded assessment (
isGraded: true,passMarkPercent: 70); same content as 11 - 12b-ungraded-quiz-item.json — QuizItem as an ungraded diagnostic pre-test (
isGraded: false); same content as 11 and 12a — demonstrates that quiz vs. exercise is structural, grading is policy - 13-content-sequence-item.json — ContentSequenceItem with carousel layout
Individual Question Examples (01-09) - RECOMMENDED
Standalone JSON files for each implemented question type with complete feedback bundles:
- 01-simple-gap-fill.json - Articles with indefinite article rule
- 02-true-false-question.json - Science fact with per-choice feedback
- 03-multiple-choice.json - Programming languages with detailed choiceFeedback
- 04-word-bank-cloze.json - Articles in context with per-gap feedback
- 05-multi-gap-cloze.json - Prepositions open cloze (FCE Part 2 style, 8 gaps)
- 06-multiple-choice-cloze.json - Vocabulary with nested gapOptionFeedback
- 07-short-answer.json - Astronomy fact recall
- 08-essay.json - IELTS Task 2 with comprehensive rubric
- 09-sentence-transformation.json - FCE Part 4 with chunk feedback
Features Demonstrated:
- Complete feedback bundle (correct, incorrect, choiceFeedback)
- Strategic hints that guide without revealing answers
- Multi-level tagging (grammar:articles:indefinite, exam:fce, level:B2)
- Realistic educational content
- Production-ready quality
Use these as templates - they showcase all features including feedback mechanisms that are integral to effective course design.
The 7 reserved-for-2027 graphic types (association, hotspot,
graphicGapMatch, graphicAssociate, graphicOrder, fileUpload,
mediaPromptedEssay) are declared in question-base.schema.json’s
enum for forward compatibility, but no example payloads ship — full
authoring and rendering support is targeted for 2027.
sample-course-with-questions.json
Complete course JSON showing:
- Full hierarchy: Course → Units → Lessons → Items → Questions
- Mixed item types: ContentItem, ExerciseItem, QuizItem
- Real-world structure: Lessons with intro content + exercises and quizzes
- Cambridge FCE alignment: Exam-style questions with proper tags
- Best practices: Proper tagging, feedback, hints, difficulty levels
Quick Start Guide
For Content Creators
Creating a Simple Course:
-
Start with a template:
cp examples/sample-course-with-questions.json my-course.json -
Modify the course metadata:
{ "title": "Your Course Title", "subtitle": "Your subtitle", "description": "Course description", "tags": ["level:B1", "grammar"] } -
Add or modify questions using the per-type example files (
01-simple-gap-fill.jsonthrough09-sentence-transformation.json, plus15-matching.jsonand the16…ordering family). -
Validate the result with any conforming consumer or the reference validator:
python ../tools/validate_course.py --course-path my-course.json
For Developers
Validating LC-JSON in code:
Implementations may use any JSON Schema (Draft 7) validator. The earlier ajv snippet (Node.js) is one example; common alternatives:
- Python:
pip install jsonschema(≥ 4.18) →Draft7Validator - Java:
everit-org/json-schemaornetworknt/json-schema-validator - Go:
santhosh-tekuri/jsonschema - Rust:
Stranger6667/jsonschema - Ruby:
voxpupuli/json-schema
The reference Python validator (tools/validate_course.py in this repository) layers domain checks (HTML allowlist, gap-marker counts, points consistency, signpost-without-objectives) on top of schema validation. Re-implementations are welcome.
Adding a new question type to the spec (PR-driven contributions):
- Create a JSON schema in
schemas/for the new type. - Add the discriminator value to
question-base.schema.json’senum. - Add a per-type example file under
examples/(e.g.17-new-type.json). - Document in
question-types-reference.md. - Add positive and negative test cases under
tests/.
Question Types — Implementation Status
Implemented (12 types, fully schema-validated as of 1.0-rc.3):
| Question Type | Example | Use Case |
|---|---|---|
simpleGapFill | 01-simple-gap-fill.json | Single gap fill-in-the-blank |
trueFalseQuestion | 02-true-false-question.json | Binary choice (True/False, Yes/No) |
multipleChoice | 03-multiple-choice.json | Single or multiple selection MCQ |
wordBankCloze | 04-word-bank-cloze.json | Gap fill from word pool |
multiGapCloze | 05-multi-gap-cloze.json | Open cloze (FCE Reading Part 2) |
multipleChoiceCloze | 06-multiple-choice-cloze.json | Dropdown cloze (FCE Reading Part 1) |
shortAnswer | 07-short-answer.json | Free text short response |
essay | 08-essay.json | Long-form writing with rubric |
sentenceTransformation | 09-sentence-transformation.json | FCE Use of English Part 4 |
matching | 15-matching.json | Term-definition matching |
ordering | 16-ordering.json | Sequence/chronological ordering |
placement | 17a-sentence-placement.json | Place items into anchored gaps in a structured passage (sentence / paragraph / sectionLabel; supports decoy gaps for TOEFL Sentence Insertion) |
Reserved (7 types declared in the discriminator enum for forward compatibility; per-type schemas and authoring/consumer support targeted for 2027):
| Question Type | Use Case |
|---|---|
association | Categorization/grouping |
hotspot | Click regions on image |
graphicGapMatch | Drag-and-drop on image |
graphicAssociate | Match text with images |
graphicOrder | Order images sequentially |
fileUpload | Document submission |
mediaPromptedEssay | Audio/video recording |
Status definitions:
- Implemented — per-type schema, example, and conformance fixtures present.
- Reserved — declared in the
question-base.schema.jsondiscriminator enum for forward compatibility; no per-type schema or example ships yet.
The 12 implemented types are the entire user-facing surface as of 1.0. The 7 reserved types are targeted for 2027.
Common Validation Errors
Error: “Number of gaps doesn’t match accepted answers”
Cause: Mismatch between numbered @@@N markers in passage and entries in gapAcceptedAnswers.
Fix: Count @@@1, @@@2, … markers in the passage and ensure gapAcceptedAnswers has matching string keys ("1", "2", …).
Error: “Unknown question type: simplegapfill”
Cause: Type discriminator uses non-canonical casing.
Fix: Use camelCase: "simpleGapFill", not "SimpleGapFill" or "simplegapfill". Per NORMATIVE.md §5.3, conforming consumers MUST reject non-canonical casings.
Error: “globalId does not match UUID pattern”
Cause: globalId is missing or not in RFC 4122 UUID form (any version; shape-only validation against the 8-4-4-4-12 hex pattern).
Fix: Generate a UUID for every Unit, Lesson, Item, and Question. Use any standard UUID library; v4 is recommended.
Error: “Unsupported specVersion ‘2.0’”
Cause: The document declares a specVersion whose major version exceeds 1.
Fix: This validator implements LC-JSON 1.x. Either update the validator or correct the specVersion to a 1.x value.
Related Documentation
NORMATIVE.md— RFC 2119 conformance requirements (the authoritative source for what implementations must do)HTML_SAFETY.md— Normative HTML allowlist forContentItem.htmlandSignpostItem.customHtml(elements, attributes, URL schemes, sanitization)ACCESSIBILITY.md— Producer/consumer accessibility obligations (alt text, captions, keyboard, language/direction) with WCAG 2.1 AA cross-references and recommended ARIA patterns; the opt-in Accessibility Profile claim binds these as MUSTs per NORMATIVE.md §12VALIDATION.md— Catalog of every documented validation rule, tagged schema-enforced / domain-validator-enforced / advisory, with citations to the enforcing site (schemas,validate_course.py, or prose). One-map view for implementers building consumers, validators, or round-trip tests.ITEM_PATTERNS.md— Informative authoring guide for items + signposts + objectivesIMPLEMENTATIONS.md— Directory of tools that produce, consume, or validate LC-JSONCONTRIBUTORS.md— Acknowledgmentsschemas/— JSON Schema files (the contract)examples/— Example documents for every artifact and question typetests/— Conformance test corpus (valid and invalid cases)question-types-reference.md— Per-type property reference
Version History
v1.0-rc.3 (2026-06-13) — second public release candidate
- Adds
LOCALIZATION.md: the language model (language/lang/supportLanguage), the single-language-per-document boundary, BCP 47 tags, and screen-reader pronunciation expectations. Bound by newNORMATIVE.md§13. - Adds a positioning page (
RATIONALE.md) explaining where LC-JSON sits among adjacent standards. - Conformance corpus expanded to 64 cases (per-type valid + invalid coverage, grading matrix, globalId-uniqueness).
- Schema change requiring a new immutable path: the prototype-era
allowedFillerWordsandprohibitExtraWordsBetweenChunksfields are dropped fromsentence-transformation.schema.json. Because/1.0-rc.2/is immutable, this lands at/1.0-rc.3/. Backwards-compatible — every rc.2-valid document remains valid under rc.3 (the removed fields were optional and are ignored on import). - Schemas published as immutable at
https://lc-json.org/1.0-rc.3/*.schema.json;/1.0-rc.1/and/1.0-rc.2/stay served and frozen; thehttps://lc-json.org/1.0/*.schema.jsonURL space is reserved for the accepted final release.
v1.0-rc.2 (2026-05-30) — first publicly announced release candidate
- Two artifact types under a common flat root:
course(hierarchical) andquestionSet(flat). - 12 user-facing question types fully implemented and schema-validated; 7 graphic/upload types reserved for a 2027 minor version.
- 23 JSON Schemas (Draft 7) covering every artifact, item type, and question type.
- 32 example files; conformance test corpus under
tests/(13 valid + 25 invalid = 38 cases). - Reference validator (
tools/validate_course.py) and conformance corpus harness (tools/run_corpus.py). promptfield correction (the rc.1 → rc.2 change):promptremains required butminLengthis0, so an empty string""is valid.promptis defined as non-authoritative for the eight symbolic question types (gap-fill family, sentence transformation, matching, ordering, placement), whose structured fields carry the question’s meaning; for those types it MAY be empty or MAY carry a brief producer-derived readable summary. A reference-validator domain rule still flags an emptyprompton the four real-content types (true/false, multiple choice, short answer, essay), where it is the question. Backwards-compatible widening — every rc.1-valid document remains valid under rc.2.- Apache 2.0 throughout. Release-candidate schemas are published as immutable at
https://lc-json.org/1.0-rc.2/*.schema.json; thehttps://lc-json.org/1.0/*.schema.jsonURL space is reserved for the accepted final release.
v1.0-rc.1 — internal release candidate (superseded, never announced)
- Frozen and served at
https://lc-json.org/1.0-rc.1/*.schema.jsonfor transparency, but never publicly announced; rc.2 is the first announced prerelease. The only substantive difference is the backwards-compatiblepromptminLength1→0correction above; the/1.0-rc.1/schema URLs remain immutable and any document valid under rc.1 is valid under rc.2.
v1.0 (2026-06-30) — accepted final release
- Publishes the rc.3 schema set unchanged at immutable
https://lc-json.org/1.0/*.schema.json— a pure URL rebase of rc.3 with zero wire/content delta (only the version pointer, the$id/$schemaURL strings, and doc version labels change). - Further accessibility deepenings (per-criterion cross-reference table, expanded ARIA patterns, screen-reader announcement timing, accessibility-conformance fixtures) are post-1.0, additive, and informative or opt-in — they do not change the 1.0 base contract (see
ACCESSIBILITY.md§11). - Any future non-breaking wire refinement lands in a new immutable minor-version path, not by mutating
1.0.
LC-JSON’s public history begins with the 1.0 release-candidate line —
1.0-rc.2(2026-05-30) was its first publicly announced release. Internal iteration before the candidate line is not reflected in the version history.
Contributing
PRs welcome. To propose a new question type or modify an existing one, see Adding a new question type above. For non-trivial changes, open an issue first to discuss the proposal.
See CONTRIBUTORS.md for acknowledgments.
Support
- GitHub Issues: open an issue on the spec repository.
- Conformance questions: consult
NORMATIVE.md; it is the authoritative source for implementer requirements.
LC-JSON Specification v1.0