Version: 1.2.0
Last Updated: 2026-01-25
Canonical URL: https://app.polyglotton.com/lesson-specification.md
This document defines the JSON format for Polyglotton language learning lessons. Use this specification when generating lessons with AI or creating them manually.
🔄 Auto-Generated: This file is automatically generated from src/lib/cardTypes/definitions.ts. Do not edit manually.
A lesson is a JSON object with metadata and an array of cards:
{
"id": "unique-lesson-id",
"title": "Lesson Title in Source Language",
"titleNative": "Lesson Title in Target Language",
"level": "A1",
"sourceLanguage": "en",
"targetLanguage": "es",
"collectionId": "my-collection",
"intro": "Brief introduction to what this lesson covers",
"learningOutcome": "What the learner will be able to do after this lesson",
"realWorldContext": "Why this is useful in real life",
"cards": []
}
| Field | Type | Description |
|---|---|---|
id |
string | Unique identifier for the lesson |
title |
string | Lesson title in the source language |
cards |
array | Array of card objects (minimum 1) |
| Field | Type | Description |
|---|---|---|
titleNative |
string | Lesson title in the target language |
level |
string | CEFR level: A1, A2, B1, B2, C1, C2 |
sourceLanguage |
string | ISO 639-1 code (e.g., en, es, de) |
targetLanguage |
string | ISO 639-1 code (e.g., en, es, de) |
collectionId |
string | Collection identifier for grouping related lessons (e.g., travel, business) |
intro |
string | Brief introduction to the lesson |
learningOutcome |
string | What the learner will achieve |
realWorldContext |
string | Why this is useful in real life |
nextStepPreview |
string | What comes next after this lesson |
tags |
string[] | Tags for categorization |
Use collectionId to organize related lessons into logical groups:
Examples:
"collectionId": "travel" - Travel-themed lessons"collectionId": "business-spanish" - Business Spanish course"collectionId": "grammar-essentials" - Grammar fundamentals"collectionId": "daily-life" - Everyday situationsBenefits:
collectionId appear grouped together in the libraryIMPORTANT: Always use ISO 639-1 two-letter language codes.
| Language | Code | Language | Code |
|---|---|---|---|
| English | en |
Spanish | es |
| German | de |
French | fr |
| Dutch | nl |
Italian | it |
| Portuguese | pt |
Hungarian | hu |
| Polish | pl |
Russian | ru |
| Japanese | ja |
Korean | ko |
| Chinese | zh |
Arabic | ar |
❌ Wrong: "sourceLanguage": "English"
âś… Correct: "sourceLanguage": "en"
All cards share these base fields:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | âś… | Unique card identifier |
exerciseType |
string | âś… | Type of exercise (see below) |
source |
string | Source/target language text | |
target |
string or string[] | Translation(s) or answer(s) | |
story |
string | Narrative scene-setting (shown BEFORE answering) | |
context |
string | Usage explanation (shown AFTER answering) | |
explanation |
string | Grammar/linguistic explanation | |
culturalNote |
string | Cultural background or etiquette | |
useCase |
string | Real-world usage tip | |
hint |
string | Hint to help the learner |
| Field | Purpose | When Shown |
|---|---|---|
| story | Narrative scene-setting. Describes what's happening. | Before answering (sets the scene) |
| context | Usage explanation. When/how to use this phrase. | After answering (learning enrichment) |
| explanation | Grammar/linguistic explanation of the pattern. | After answering |
| culturalNote | Cultural background or etiquette notes. | After answering |
| useCase | Practical tip for real-life use. | After answering |
Example distinction:
{
"id": "card-001",
"exerciseType": "translation",
"source": "Hello, how are you?",
"target": ["Hola, ¿cómo estás?", "¿Cómo estás?"],
"story": "You meet your Spanish friend Ana on the street.",
"context": "Informal greeting used with friends and peers",
"explanation": "¿Cómo estás? uses the informal 'tú' form"
}
For reverse translation, the app will show the target text (target language) and the user must type the source text (source language).
source and target always refer to the lesson's configured source/target languages, regardless of card type.
{
"id": "card-002",
"exerciseType": "reverse",
"source": "Hello, how are you?", // source language (what user must type)
"target": ["Hola, ¿cómo estás?", "¿Cómo estás?"], // target language (what is shown)
"context": "Common greeting response"
}
{
"id": "card-003",
"exerciseType": "multiple_choice",
"question": "How do you say 'thank you' in Spanish?",
"options": ["Gracias", "Por favor", "De nada", "Hola"],
"correctIndex": 0,
"explanation": "Gracias is the standard way to say thank you"
}
{
"id": "card-004",
"exerciseType": "cloze",
"source": "Yo ___ cafĂ© todos los dĂas.",
"target": ["bebo", "tomo"],
"story": "You're describing your daily habits to a new friend.",
"hint": "First person singular verb for drinking",
"context": "Used when talking about regular habits or routines",
"explanation": "'Beber' and 'tomar' both mean 'to drink' - 'tomar' is more common in Latin America"
}
{
"id": "card-005",
"exerciseType": "conversation",
"dialogue": [
{ "speaker": "bot", "text": "Hi! How can I help you today?" },
{ "speaker": "user", "text": "I'd like a coffee, please." },
{ "speaker": "bot", "text": "Sure—small or large?" },
{ "speaker": "user", "text": "Large, please." }
],
"userPrompts": [
{
"prompt": "Hi! How can I help you today?",
"acceptableResponses": [
"I'd like a coffee, please.",
"Can I have a coffee, please?"
]
},
{
"prompt": "Sure—small or large?",
"acceptableResponses": ["Large, please.", "A large one, please."]
}
],
"context": "Ordering at a café"
}
{
"id": "card-006",
"exerciseType": "listening",
"transcript": "Buenos dĂas, ÂżquĂ© tal?",
"question": "What time of day is this greeting for?",
"options": ["Morning", "Afternoon", "Evening", "Night"],
"correctIndex": 0
}
{
"id": "card-013",
"exerciseType": "dictation",
"transcript": "Buenos dĂas, ÂżquĂ© tal?", // what the learner hears (used for TTS)
"correctText": "Buenos dĂas, ÂżquĂ© tal?", // what the learner must type
"audioUrl": "https://example.com/audio.mp3", // optional, ONLY INCLUDE THIS IF YOU HAVE A VALID MP3 URL that is relevant, provided by the user.
"story": "A friend greets you in the morning.",
"context": "Common morning greeting"
}
{
"id": "card-014",
"exerciseType": "matching",
"question": "Match each phrase to its meaning",
"pairs": [
{ "left": "Buenos dĂas", "right": "Good morning" },
{ "left": "Buenas noches", "right": "Good night" },
{ "left": "Gracias", "right": "Thank you" }
],
"context": "Common everyday phrases"
}
{
"id": "card-007",
"exerciseType": "story_fragment",
"story": "MarĂa walks into a cafĂ©. The waiter approaches her table.",
"source": "Buenos dĂas, ÂżquĂ© le pongo?",
"question": "What is the waiter asking MarĂa?",
"options": ["What would you like?", "How are you?", "Where are you from?", "What time is it?"],
"correctIndex": 0
}
{
"id": "card-008",
"exerciseType": "explanation_then_apply",
"explanation": "In Spanish, adjectives must agree in gender and number with the noun they modify.",
"examples": [
{ "target": "El gato negro", "source": "The black cat (masculine)" },
{ "target": "La gata negra", "source": "The black cat (feminine)" }
],
"challenge": "Choose the correct form: 'La casa ___' (big)",
"options": ["grande", "grandes", "gran", "grandos"],
"correctIndex": 0
}
Important grading note: free-form writing is only auto-gradable if you provide either:
acceptableResponses (best when the expected output is a single word/phrase), ormetadata.grading (best when you want to allow longer answers but still validate required elements).{
"id": "card-009",
"exerciseType": "production_challenge",
"scenario": "You're at a restaurant and want to order a coffee with milk.",
"source": "Order a coffee with milk politely",
"acceptableResponses": [
"Un café con leche, por favor",
"¿Me pone un café con leche?",
"Quiero un café con leche, por favor"
],
"hint": "Include a polite phrase like 'por favor'",
"context": "Restaurant ordering"
}
Use this when there are many valid paraphrases. The learner can write freely, but the answer must include certain required words/phrases.
⚠️ Field usage (consistent with other card types):
story: Essential reading/context shown BEFORE answering (e.g., "The text says: '...'")hint: Clue/tip shown BEFORE answering (e.g., "It starts with meg-...")context: Usage notes shown AFTER answering (e.g., "When to use this phrase"){
"id": "card-010",
"exerciseType": "production_challenge",
"scenario": "You are explaining what an old dialect word means.",
"source": "Translate the meaning into the synonym used in the text.",
"story": "The text says: '...vagy ahogy Ĺ‘k mondták, annyira zsöndĂtettĂ©k...'",
"hint": "It starts with meg-...",
"acceptableResponses": ["meghizlalták"],
"context": "This is a regional dialect variation still used in rural Hungary",
"metadata": {
"grading": {
"mode": "keywords",
"required": ["meghizlalták"]
}
}
}
Note: This card type is available but not included in default lesson presets. It can still be used in manually created lessons.
{
"id": "card-010",
"exerciseType": "cultural_insight",
"culturalInsight": "In Spain, lunch (la comida) is typically the largest meal of the day, served between 2-4 PM. Dinner (la cena) is lighter and eaten around 9-10 PM.",
"question": "When is the main meal typically served in Spain?",
"options": ["2-4 PM", "12-1 PM", "6-7 PM", "8-9 AM"],
"correctIndex": 0,
"reasoning": "Spanish culture has a different meal schedule than many other countries"
}
{
"id": "card-012",
"exerciseType": "comprehensive_reading",
"readingText": "MarĂa vive en Madrid. Ella trabaja en una oficina cerca del centro. Todos los dĂas, toma el metro para ir al trabajo. Le gusta mucho su trabajo porque tiene buenos compañeros.",
"comprehensionQuestions": [
{
"question": "ÂżDĂłnde vive MarĂa?",
"type": "multiple_choice",
"options": ["Madrid", "Barcelona", "Valencia", "Sevilla"],
"correctIndex": 0
},
{
"question": "ÂżCĂłmo va MarĂa al trabajo?",
"type": "multiple_choice",
"options": ["En metro", "En autobĂşs", "En coche", "A pie"],
"correctIndex": 0
},
{
"question": "¿Por qué le gusta su trabajo?",
"type": "short_answer",
"answer": ["tiene buenos compañeros", "buenos compañeros", "por los compañeros"]
}
]
}
Notes:
correctIndex to specify which option is correct (0-indexed). Requires options array.answer field with a string or array of acceptable answers. More challenging for learners.{
"id": "card-014",
"exerciseType": "speaking",
"prompt": "Say this phrase out loud",
"target": ["Buenos dĂas, ÂżcĂłmo está usted?", "Buenos dĂas, ÂżcĂłmo está?"],
"translation": "Good morning, how are you?",
"hint": "Practice the formal greeting",
"context": "Use this when greeting someone formally",
"explanation": "Multiple acceptable pronunciations are supported"
}
Notes:
target can be a string or array of strings for synonym support{
"id": "card-015",
"exerciseType": "reordering",
"shuffledWords": ["es", "libro", "un", "Este"],
"correctOrder": ["Este", "es", "un", "libro"],
"translation": "This is a book",
"hint": "Start with the demonstrative pronoun",
"context": "Basic sentence structure practice"
}
| Level | Description | Vocabulary & Grammar |
|---|---|---|
| A1 | Complete beginner | Very simple vocabulary, short sentences, basic present tense. Topics: greetings, numbers, basic needs. |
| A2 | Elementary | Simple everyday expressions, basic grammar structures, present and simple past tense. |
| B1 | Intermediate | Can handle most travel situations, express opinions, use various tenses. |
| B2 | Upper intermediate | Complex sentences, abstract topics, nuanced expressions. |
| C1 | Advanced | Sophisticated vocabulary, idioms, subtle meanings, complex grammar. |
| C2 | Mastery | Near-native fluency, literary expressions, cultural nuances. |
Unique IDs: Every card must have a unique id field (e.g., card-001, card-002)
Progressive Difficulty: Start with simpler cards, gradually increase complexity
Contextual Learning: Include real-world usage context for each card
Multiple Acceptable Answers: For translation cards, provide an array of acceptable answers
Cultural Notes: Add cultural context where relevant
Intrinsic Motivation: Make content personally relevant and practically useful
Language Separation: The source field in cloze cards must contain ONLY target language text. Never mix languages. Use story or context for source language explanations.
Language Codes: Always use ISO 639-1 two-letter codes (en, es, de, fr, hu, nl, etc.) NOT full language names
Collection Organization: Use collectionId to group related lessons into coherent series or topics
{
"id": "greetings-basics-01",
"title": "Basic Greetings",
"titleNative": "Saludos básicos",
"level": "A1",
"sourceLanguage": "en",
"targetLanguage": "es",
"collectionId": "spanish-fundamentals",
"intro": "Learn essential Spanish greetings for everyday situations.",
"learningOutcome": "You will be able to greet people and introduce yourself in Spanish.",
"realWorldContext": "These phrases are used daily in Spanish-speaking countries.",
"cards": [
{
"id": "card-001",
"exerciseType": "translation",
"source": "Hello",
"target": ["Hola"],
"context": "Universal greeting, used any time of day",
"explanation": "Hola is informal and friendly"
},
{
"id": "card-002",
"exerciseType": "multiple_choice",
"question": "How do you say 'Good morning' in Spanish?",
"options": ["Buenos dĂas", "Buenas tardes", "Buenas noches", "Hola"],
"correctIndex": 0,
"explanation": "Buenos dĂas is used until around noon"
},
{
"id": "card-003",
"exerciseType": "cloze",
"source": "ÂżCĂłmo ___ llamas?",
"target": ["te"],
"hint": "Reflexive pronoun for 'tĂş'",
"context": "Asking someone's name informally",
"explanation": "Llamarse is a reflexive verb meaning 'to be called'"
}
]
}
Lessons are validated using Zod schemas. The app will automatically:
For the full schema definition, see the source code at:
src/lib/schemas/lesson.ts
You can use any LLM (ChatGPT, Claude, Gemini, Mistral, etc.) to generate lessons. Simply:
Example prompt:
Read https://app.polyglotton.com/lesson-specification.html and generate a Spanish lesson about ordering food at a restaurant, level A2, for English speakers. Include 10 cards with a mix of translation, cloze, and multiple choice exercises.
This specification is maintained at: static/lesson-specification.md
Generated from: src/lib/cardTypes/definitions.ts