37 KiB
LEARNING CONTENT GUIDE
Version: 1.0.0
Last Updated: 2024
Purpose: Comprehensive guide for AI to understand and create learning content in the Subject → Chapter → Lesson hierarchy
Table of Contents
- Overview
- Content Hierarchy
- Subject Structure
- Chapter Structure
- Lesson Structure
- Lesson Content Types
- Exercise Types
- API Workflow
- Code Examples
- Validation Checklist
- Common Mistakes
- AI Integration Tips
Overview
The learning content system is structured in a three-level hierarchy:
Subject (Course/Curriculum)
└── Chapter (Unit/Topic)
└── Lesson (Individual Learning Activity)
Each level serves a specific purpose:
- Subject: Represents a complete course (e.g., "English Grade 1", "Math Grade 5")
- Chapter: Represents a major topic within a subject (e.g., "Unit 1: My Family", "Chapter 3: Fractions")
- Lesson: Represents individual learning activities with specific content types
Content Hierarchy
Database Schema
┌─────────────┐
│ Subject │
│ (UUID) │
└──────┬──────┘
│ 1:N
│
┌──────▼──────┐
│ Chapter │
│ (UUID) │
└──────┬──────┘
│ 1:N
│
┌──────▼──────┐
│ Lesson │
│ (UUID) │
└─────────────┘
Relationships
- One Subject can have many Chapters
- One Chapter can have many Lessons
- All IDs are UUID (for security against crawlers)
- Foreign keys:
subject_idin Chapter,chapter_idin Lesson
Subject Structure
Database Model: Subject
Table: subjects
Required Fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
UUID | Primary key | 550e8400-e29b-41d4-a716-446655440000 |
subject_code |
VARCHAR(20) | Unique subject code | ENG-G1 |
subject_name |
VARCHAR(100) | Subject name (Vietnamese) | Tiếng Anh Lớp 1 |
Optional Fields:
| Field | Type | Default | Description |
|---|---|---|---|
subject_name_en |
VARCHAR(100) | NULL | English name |
description |
TEXT | NULL | Subject description |
is_active |
BOOLEAN | true | Active status |
is_premium |
BOOLEAN | false | Premium content flag |
is_training |
BOOLEAN | false | Training content flag |
is_public |
BOOLEAN | false | Public self-learning flag |
required_role |
VARCHAR(50) | NULL | Required role to access |
Subject Access Control
The Subject model includes access control fields:
is_premium: Content requires subscriptionis_training: Content for staff trainingis_public: Available for public self-learningrequired_role: Specific role required (e.g., "teacher", "admin")
Example Subject
{
"subject_code": "ENG-G1",
"subject_name": "Tiếng Anh Lớp 1",
"subject_name_en": "English Grade 1",
"description": "Basic English course for Grade 1 students",
"is_active": true,
"is_premium": false,
"is_public": true
}
Chapter Structure
Database Model: Chapter
Table: chapters
Required Fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
UUID | Primary key | 550e8400-e29b-41d4-a716-446655440001 |
subject_id |
UUID | Foreign key to Subject | 550e8400-e29b-41d4-a716-446655440000 |
chapter_number |
INTEGER | Sequential chapter number | 1 |
chapter_title |
VARCHAR(200) | Chapter title | Unit 1: My Family |
Optional Fields:
| Field | Type | Default | Description |
|---|---|---|---|
chapter_description |
TEXT | NULL | Chapter description |
duration_minutes |
INTEGER | NULL | Estimated duration |
is_published |
BOOLEAN | false | Published status |
display_order |
INTEGER | NULL | Custom display order |
Chapter Numbering
chapter_number: Sequential number (1, 2, 3, ...)display_order: Optional custom order (for reordering without renumbering)
Example Chapter
{
"subject_id": "550e8400-e29b-41d4-a716-446655440000",
"chapter_number": 1,
"chapter_title": "Unit 1: My Family",
"chapter_description": "Learn about family members and relationships",
"duration_minutes": 120,
"is_published": true,
"display_order": 1
}
Lesson Structure
Database Model: Lesson
Table: lessons
Required Fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
UUID | Primary key | 550e8400-e29b-41d4-a716-446655440010 |
chapter_id |
UUID | Foreign key to Chapter | 550e8400-e29b-41d4-a716-446655440001 |
lesson_number |
INTEGER | Sequential lesson number | 1 |
lesson_title |
VARCHAR(200) | Lesson title | Family Vocabulary |
lesson_type |
ENUM | Content delivery type | json_content or url_content |
Optional Fields:
| Field | Type | Default | Description |
|---|---|---|---|
lesson_description |
TEXT | NULL | Lesson description |
lesson_content_type |
ENUM | NULL | Content category: vocabulary, grammar, phonics, review, mixed |
content_json |
JSON | NULL | JSON content structure |
content_url |
VARCHAR(500) | NULL | URL for external content |
content_type |
VARCHAR(50) | NULL | URL content type: video, audio, pdf, image, interactive |
duration_minutes |
INTEGER | NULL | Estimated duration |
is_published |
BOOLEAN | false | Published status |
is_free |
BOOLEAN | false | Free trial access |
display_order |
INTEGER | 0 | Custom display order |
thumbnail_url |
VARCHAR(500) | NULL | Lesson thumbnail |
Lesson Types
1. lesson_type (Content Delivery)
json_content: Content is stored incontent_jsonfield (structured data)url_content: Content is external, referenced bycontent_url
2. lesson_content_type (Content Category)
vocabulary: Vocabulary learning lessongrammar: Grammar rules and practicephonics: Pronunciation and phonicsreview: Review lesson combining multiple typesmixed: Mixed content (custom combination)
Validation Rules
- If
lesson_type = 'json_content', thencontent_jsonis required - If
lesson_type = 'url_content', thencontent_urlis required lesson_content_typeandcontent_json.typeshould match for consistency- Lesson numbers should be sequential within a chapter
Lesson Content Types
1. Vocabulary Lesson
Purpose: Teaching vocabulary with word lists and exercises
lesson_content_type: vocabulary
content_json Structure:
{
"type": "vocabulary",
"words": [
"mother",
"father",
"sister",
"brother"
],
"exercises": [
{
"type": "match",
"question": "Match the words with pictures",
"items": [
{ "word": "mother", "image": "https://..." },
{ "word": "father", "image": "https://..." }
]
}
]
}
Key Fields:
words: Array of vocabulary words (strings). System will automatically lookup these words in theVocabtable when rendering the lessonexercises: Array of practice exercises
Important Notes:
- ⚠️ No need to use
vocabulary_idsanymore! - Just provide a simple array of words like
["mother", "father", "sister"] - The system will search for these words in the
Vocabtable bybase_wordfield - If a word doesn't exist in the database, the system will handle it gracefully
- For custom/inline vocabulary, you can also use detailed objects:
{
"type": "vocabulary",
"words": [
{
"word": "mother",
"translation": "mẹ",
"image": "https://cdn.sena.tech/vocab/mother.jpg",
"audio": "https://cdn.sena.tech/audio/mother.mp3",
"phonetic": "/ˈmʌð.ər/"
}
]
}
When to use simple array vs detailed objects:
- Use simple array (
["mother", "father"]) when words already exist inVocabtable - Use detailed objects when you need custom/temporary vocabulary not in the database
2. Grammar Lesson
Purpose: Teaching grammar rules with examples and practice
lesson_content_type: grammar
content_json Structure:
{
"type": "grammar",
"grammar_points": ["Present Simple", "Present Continuous"],
"sentences": [
"I eat an apple.",
"She eats an apple.",
"They are eating apples."
],
"exercises": [
{
"type": "fill_blank",
"question": "She ___ (eat) an apple every day.",
"answer": "eats",
"options": ["eat", "eats", "eating"]
}
]
}
Key Fields:
grammar_points: Array of grammar names (e.g.,["Present Simple"]). System will search for matching grammar patterns in theGrammartablesentences: Array of example sentences demonstrating the grammarexercises: Array of practice exercises
Important Notes:
- ⚠️ No need to use
grammar_idsanymore! - Just provide grammar names like
["Present Simple"]or example sentences - The system will search in the
Grammartable bytitleor analyze sentence patterns - You can also use just sentences without grammar_points:
{
"type": "grammar",
"sentences": [
"I eat an apple.",
"She eats an apple."
],
"exercises": [...]
}
Alternative: Inline Grammar Rules
For custom grammar explanations:
{
"type": "grammar",
"rules": [
{
"rule_name": "Present Simple",
"formula": "S + V(s/es)",
"explanation": "Used for habits and facts"
}
],
"sentences": [...],
"exercises": [...]
}
3. Phonics Lesson
Purpose: Teaching pronunciation with IPA and sound practice
lesson_content_type: phonics
content_json Structure:
{
"type": "phonics",
"phonics_rules": [
{
"ipa": "/æ/",
"sound_name": "short a",
"description": "As in 'cat', 'hat'",
"audio": "https://cdn.sena.tech/phonics/ae.mp3",
"words": [
{
"word": "cat",
"phonetic": "/kæt/",
"audio": "https://cdn.sena.tech/audio/cat.mp3",
"image": "https://cdn.sena.tech/img/cat.jpg"
},
{
"word": "hat",
"phonetic": "/hæt/",
"audio": "https://cdn.sena.tech/audio/hat.mp3",
"image": "https://cdn.sena.tech/img/hat.jpg"
}
]
}
],
"exercises": [
{
"type": "listen_repeat",
"question": "Listen and repeat",
"audio": "https://cdn.sena.tech/audio/cat.mp3",
"word": "cat"
},
{
"type": "identify_sound",
"question": "Which word has the /æ/ sound?",
"options": ["cat", "cut", "cot"],
"answer": "cat"
}
]
}
Key Fields:
phonics_rules: Array of phonics rules with IPA notationipa: International Phonetic Alphabet symbol (e.g.,/æ/,/iː/)sound_name: Friendly name for the sound (e.g., "short a", "long e")words: Example words demonstrating the soundexercises: Pronunciation practice exercises
4. Review Lesson
Purpose: Reviewing multiple content types (vocabulary + grammar + phonics)
lesson_content_type: review
content_json Structure:
{
"type": "review",
"sections": [
{
"section_type": "vocabulary",
"title": "Family Vocabulary Review",
"words": ["mother", "father", "sister", "brother"],
"exercises": [
{
"type": "match",
"question": "Match family members",
"items": [...]
}
]
},
{
"section_type": "grammar",
"title": "Present Simple Review",
"grammar_points": ["Present Simple"],
"sentences": ["I eat an apple", "She eats an apple"],
"exercises": [
{
"type": "fill_blank",
"question": "She ___ an apple.",
"answer": "eats",
"options": ["eat", "eats", "eating"]
}
]
},
{
"section_type": "phonics",
"title": "Short A Sound Review",
"phonics_rules": [
{
"ipa": "/æ/",
"words": ["cat", "hat", "bat"]
}
],
"exercises": [...]
}
],
"overall_exercises": [
{
"type": "mixed_quiz",
"questions": [
{
"type": "vocabulary",
"question": "What is 'mẹ' in English?",
"answer": "mother",
"options": ["mother", "father", "sister"]
},
{
"type": "grammar",
"question": "She ___ an apple.",
"answer": "eats",
"options": ["eat", "eats", "eating"]
},
{
"type": "phonics",
"question": "Which word has the /æ/ sound?",
"answer": "cat",
"options": ["cat", "cut", "cot"]
}
]
}
]
}
Key Fields:
sections: Array of review sections (vocabulary, grammar, phonics)section_type: Type of each section (vocabulary,grammar,phonics)words: For vocabulary sections - system will lookup in Vocab tablegrammar_points/sentences: For grammar sections - system will lookup in Grammar tableoverall_exercises: Mixed exercises combining all sections
Review Lesson Guidelines:
- Each section should review 1-3 key concepts from previous lessons
- Use word arrays for vocabulary (e.g.,
["mother", "father"]) - Use sentence arrays or grammar names for grammar (e.g.,
["I eat an apple"]or["Present Simple"]) - Include exercises for each section
- Add
overall_exercisesfor comprehensive review - Use
mixed_quizto test understanding across all content types
Exercise Types
Common exercise types across all lesson types:
1. Match Exercise
Purpose: Match items (words to images, words to translations)
{
"type": "match",
"question": "Match the words with pictures",
"items": [
{ "word": "mother", "image": "https://cdn.sena.tech/img/mother.jpg" },
{ "word": "father", "image": "https://cdn.sena.tech/img/father.jpg" }
]
}
2. Fill in the Blank
Purpose: Complete sentences with correct words
{
"type": "fill_blank",
"question": "This is my ___",
"answer": "mother",
"options": ["mother", "father", "sister"]
}
3. Multiple Choice
Purpose: Select correct answer from options
{
"type": "multiple_choice",
"question": "What is 'mẹ' in English?",
"options": ["mother", "father", "sister", "brother"],
"answer": "mother"
}
4. Arrange Words
Purpose: Arrange words to form correct sentence
{
"type": "arrange_words",
"question": "Arrange: apple / eat / I / an",
"answer": "I eat an apple",
"words": ["apple", "eat", "I", "an"]
}
5. Listen and Repeat (Phonics)
Purpose: Practice pronunciation
{
"type": "listen_repeat",
"question": "Listen and repeat",
"audio": "https://cdn.sena.tech/audio/cat.mp3",
"word": "cat"
}
6. Identify Sound (Phonics)
Purpose: Identify words with specific sound
{
"type": "identify_sound",
"question": "Which word has the /æ/ sound?",
"options": ["cat", "cut", "cot"],
"answer": "cat"
}
7. True/False
Purpose: Validate statements
{
"type": "true_false",
"question": "The word 'mother' means 'mẹ'.",
"answer": true
}
8. Mixed Quiz (Review Lessons)
Purpose: Combine multiple question types
{
"type": "mixed_quiz",
"questions": [
{
"type": "vocabulary",
"question": "What is 'mẹ' in English?",
"answer": "mother",
"options": ["mother", "father", "sister"]
},
{
"type": "grammar",
"question": "She ___ an apple.",
"answer": "eats",
"options": ["eat", "eats", "eating"]
}
]
}
API Workflow
Step-by-Step Guide to Create Learning Content
Step 1: Create Subject
Endpoint: POST /api/subjects
Request:
{
"subject_code": "ENG-G1",
"subject_name": "Tiếng Anh Lớp 1",
"subject_name_en": "English Grade 1",
"description": "Basic English for Grade 1",
"is_active": true,
"is_public": true
}
Response:
{
"success": true,
"message": "Subject created successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"subject_code": "ENG-G1",
...
}
}
Save the id for next step.
Step 2: Create Chapter
Endpoint: POST /api/chapters
Request:
{
"subject_id": "550e8400-e29b-41d4-a716-446655440000",
"chapter_number": 1,
"chapter_title": "Unit 1: My Family",
"chapter_description": "Learn about family members",
"duration_minutes": 120,
"is_published": true
}
Response:
{
"success": true,
"message": "Chapter created successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"subject_id": "550e8400-e29b-41d4-a716-446655440000",
...
}
}
Save the id for next step.
Step 3: Create Vocabulary Lesson (using word list)
Endpoint: POST /api/learning-content/lessons
Note: ⚠️ No need to create Vocab entries first! Just use a simple word list. System will lookup words in Vocab table when rendering.
Request:
{
"chapter_id": "550e8400-e29b-41d4-a716-446655440001",
"lesson_number": 1,
"lesson_title": "Family Vocabulary",
"lesson_type": "json_content",
"lesson_content_type": "vocabulary",
"content_json": {
"type": "vocabulary",
"words": ["mother", "father", "sister", "brother"],
"exercises": [
{
"type": "match",
"question": "Match family members",
"items": [
{ "word": "mother", "image": "https://cdn.sena.tech/img/mother.jpg" }
]
}
]
},
"duration_minutes": 30,
"is_published": true
}
Response:
{
"success": true,
"message": "Lesson created successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440010",
...
}
}
Step 4: Create Grammar Lesson (using sentences)
Endpoint: POST /api/learning-content/lessons
Note: ⚠️ No need to create Grammar entries first! Just provide grammar names or example sentences. System will find matching patterns in Grammar table.
Request:
{
"chapter_id": "550e8400-e29b-41d4-a716-446655440001",
"lesson_number": 2,
"lesson_title": "Present Simple",
"lesson_type": "json_content",
"lesson_content_type": "grammar",
"content_json": {
"type": "grammar",
"grammar_points": ["Present Simple"],
"sentences": ["I eat an apple", "She eats an apple"],
"exercises": [
{
"type": "fill_blank",
"question": "She ___ an apple.",
"answer": "eats",
"options": ["eat", "eats", "eating"]
}
]
},
"duration_minutes": 30,
"is_published": true
}
Response:
{
"success": true,
"message": "Lesson created successfully",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440011",
...
}
}
Step 5: Create Review Lesson
Endpoint: POST /api/learning-content/lessons
Request:
{
"chapter_id": "550e8400-e29b-41d4-a716-446655440001",
"lesson_number": 3,
"lesson_title": "Unit Review",
"lesson_type": "json_content",
"lesson_content_type": "review",
"content_json": {
"type": "review",
"sections": [
{
"section_type": "vocabulary",
"title": "Family Words",
"words": ["mother", "father", "sister"]
},
{
"section_type": "grammar",
"title": "Present Simple",
"grammar_points": ["Present Simple"],
"sentences": ["I eat an apple", "She eats an apple"]
}
],
"overall_exercises": [
{
"type": "mixed_quiz",
"questions": [
{
"type": "vocabulary",
"question": "What is 'mẹ' in English?",
"answer": "mother"
}
]
}
]
},
"duration_minutes": 40,
"is_published": true
}
API Endpoints Summary
{ "word": "hat", "phonetic": "/hæt/" }
]
}
],
"exercises": [
{
"type": "listen_repeat",
"audio": "https://cdn.sena.tech/audio/cat.mp3",
"word": "cat"
}
]
}, "duration_minutes": 25, "is_published": true }
**Example 4: Review Lesson**
```json
{
"chapter_id": "550e8400-e29b-41d4-a716-446655440001",
"lesson_number": 4,
"lesson_title": "Unit 1 Review",
"lesson_type": "json_content",
"lesson_content_type": "review",
"content_json": {
"type": "review",
"sections": [
{
"section_type": "vocabulary",
"title": "Family Words",
"vocabulary_ids": ["550e8400-e29b-41d4-a716-446655440020"]
},
{
"section_type": "grammar",
"title": "Present Simple",
"grammar_ids": ["550e8400-e29b-41d4-a716-446655440030"]
}
],
"overall_exercises": [
{
"type": "mixed_quiz",
"questions": [
{
"type": "vocabulary",
"question": "What is 'mẹ' in English?",
"answer": "mother"
}
]
}
]
},
"duration_minutes": 40,
"is_published": true
}
API Endpoints Summary
| Endpoint | Method | Purpose |
|---|---|---|
/api/subjects |
POST | Create subject |
/api/subjects |
GET | Get all subjects |
/api/subjects/:id |
GET | Get subject by ID |
/api/subjects/:id |
PUT | Update subject |
/api/subjects/:id |
DELETE | Delete subject |
/api/chapters |
POST | Create chapter |
/api/chapters |
GET | Get all chapters |
/api/chapters/:id |
GET | Get chapter by ID |
/api/chapters/:id |
PUT | Update chapter |
/api/chapters/:id |
DELETE | Delete chapter |
/api/vocab |
POST | Create vocabulary |
/api/vocab |
GET | Get all vocabulary |
/api/grammar |
POST | Create grammar rule |
/api/grammar |
GET | Get all grammar rules |
/api/learning-content/lessons |
POST | Create lesson |
/api/learning-content/lessons |
GET | Get all lessons |
/api/learning-content/lessons/:id |
GET | Get lesson by ID |
/api/learning-content/lessons/:id |
PUT | Update lesson |
/api/learning-content/lessons/:id |
DELETE | Delete lesson |
/api/learning-content/lessons/chapter/:chapter_id |
GET | Get lessons by chapter |
/api/learning-content/guide |
GET | Get learning content guide (JSON) |
Code Examples
Example 1: Complete Workflow (JavaScript)
const axios = require('axios');
const API_URL = 'http://localhost:3000/api';
const TOKEN = 'your-auth-token';
// Headers with authentication
const headers = {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json'
};
async function createLearningContent() {
try {
// Step 1: Create Subject
const subjectRes = await axios.post(`${API_URL}/subjects`, {
subject_code: 'ENG-G1',
subject_name: 'Tiếng Anh Lớp 1',
subject_name_en: 'English Grade 1',
is_public: true
}, { headers });
const subjectId = subjectRes.data.data.id;
console.log('Subject created:', subjectId);
// Step 2: Create Chapter
const chapterRes = await axios.post(`${API_URL}/chapters`, {
subject_id: subjectId,
chapter_number: 1,
chapter_title: 'Unit 1: My Family',
is_published: true
}, { headers });
const chapterId = chapterRes.data.data.id;
console.log('Chapter created:', chapterId);
// Step 3: Create Vocabulary Lesson (using word list - NO NEED to create Vocab first!)
const lesson1Res = await axios.post(`${API_URL}/learning-content/lessons`, {
chapter_id: chapterId,
lesson_number: 1,
lesson_title: 'Family Vocabulary',
lesson_type: 'json_content',
lesson_content_type: 'vocabulary',
content_json: {
type: 'vocabulary',
words: ['mother', 'father', 'sister', 'brother'],
exercises: [
{
type: 'match',
question: 'Match family members',
items: [
{ word: 'mother', image: 'https://...' }
]
}
]
},
is_published: true
}, { headers });
console.log('Vocabulary lesson created:', lesson1Res.data.data.id);
// Step 4: Create Grammar Lesson (using sentences - NO NEED to create Grammar first!)
const lesson2Res = await axios.post(`${API_URL}/learning-content/lessons`, {
chapter_id: chapterId,
lesson_number: 2,
lesson_title: 'Present Simple',
lesson_type: 'json_content',
lesson_content_type: 'grammar',
content_json: {
type: 'grammar',
grammar_points: ['Present Simple'],
sentences: ['I eat an apple', 'She eats an apple'],
exercises: [
{
type: 'fill_blank',
question: 'She ___ an apple.',
answer: 'eats',
options: ['eat', 'eats', 'eating']
}
]
},
is_published: true
}, { headers });
console.log('Grammar lesson created:', lesson2Res.data.data.id);
// Step 5: Create Review Lesson
const lesson3Res = await axios.post(`${API_URL}/learning-content/lessons`, {
chapter_id: chapterId,
lesson_number: 3,
lesson_title: 'Review Lesson',
lesson_type: 'json_content',
lesson_content_type: 'review',
content_json: {
type: 'review',
sections: [
{
section_type: 'vocabulary',
title: 'Vocabulary Review',
words: ['mother', 'father', 'sister']
},
{
section_type: 'grammar',
title: 'Grammar Review',
grammar_points: ['Present Simple'],
sentences: ['I eat an apple']
}
],
overall_exercises: [
{
type: 'mixed_quiz',
questions: [
{
type: 'vocabulary',
question: 'What is "mẹ" in English?',
answer: 'mother'
}
]
}
]
},
is_published: true
}, { headers });
console.log('Review lesson created:', lesson3Res.data.data.id);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
createLearningContent();
Example 2: Query Lessons by Chapter
lesson_content_type: 'vocabulary',
content_json: {
type: 'vocabulary',
words: ['mother', 'father', 'sister'],
exercises: [
{
type: 'match',
question: 'Match family members',
items: [
{ word: 'mother', image: 'https://...' }
]
}
]
},
is_published: true
}, { headers });
console.log('Vocabulary lesson created:', lesson1Res.data.data.id);
// Step 6: Create Grammar Lesson
const lesson2Res = await axios.post(`${API_URL}/learning-content/lessons`, {
chapter_id: chapterId,
lesson_number: 2,
lesson_title: 'Present Simple',
lesson_type: 'json_content',
lesson_content_type: 'grammar',
content_json: {
type: 'grammar',
grammar_points: ['Present Simple'],
sentences: ['I eat an apple', 'She eats an apple'],
exercises: [
{
type: 'fill_blank',
question: 'She ___ an apple.',
answer: 'eats',
options: ['eat', 'eats', 'eating']
}
]
},
is_published: true
}, { headers });
console.log('Grammar lesson created:', lesson2Res.data.data.id);
// Step 7: Create Review Lesson
const lesson3Res = await axios.post(`${API_URL}/learning-content/lessons`, {
chapter_id: chapterId,
lesson_number: 3,
lesson_title: 'Review Lesson',
lesson_type: 'json_content',
lesson_content_type: 'review',
content_json: {
type: 'review',
sections: [
{
section_type: 'vocabulary',
title: 'Vocabulary Review',
words: ['mother', 'father', 'sister']
},
{
section_type: 'grammar',
title: 'Grammar Review',
grammar_points: ['Present Simple'],
sentences: ['I eat an apple']
}
],
overall_exercises: [
{
type: 'mixed_quiz',
questions: [
{
type: 'vocabulary',
question: 'What is "mẹ" in English?',
answer: 'mother'
}
]
}
]
},
is_published: true
}, { headers });
console.log('Review lesson created:', lesson3Res.data.data.id);
} catch (error) { console.error('Error:', error.response?.data || error.message); } }
createLearningContent();
---
### Example 2: Query Lessons by Chapter
```javascript
async function getLessonsByChapter(chapterId) {
try {
const response = await axios.get(
`${API_URL}/learning-content/lessons/chapter/${chapterId}`
);
console.log(`Found ${response.data.count} lessons`);
response.data.data.forEach(lesson => {
console.log(`- ${lesson.lesson_number}. ${lesson.lesson_title} (${lesson.lesson_content_type})`);
});
return response.data.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
Example 3: Update Lesson Content
async function updateLessonExercises(lessonId, newExercises) {
try {
// First, get the lesson
const getRes = await axios.get(`${API_URL}/learning-content/lessons/${lessonId}`);
const lesson = getRes.data.data;
// Update content_json with new exercises
const updatedContentJson = {
...lesson.content_json,
exercises: newExercises
};
// Send update request
const updateRes = await axios.put(
`${API_URL}/learning-content/lessons/${lessonId}`,
{ content_json: updatedContentJson },
{ headers }
);
console.log('Lesson updated successfully');
return updateRes.data.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
Validation Checklist
Before creating lessons, validate:
- Subject exists: Check that
subject_idis valid - Chapter exists: Check that
chapter_idis valid - Lesson type matches content:
lesson_type = 'json_content'→content_jsonis presentlesson_type = 'url_content'→content_urlis present
- Content type consistency:
lesson_content_typematchescontent_json.type - Valid UUIDs: All
vocabulary_idsandgrammar_idsreference existing records - Exercise structure: All exercises have required fields (
type,question,answer) - URLs are accessible: Check all
image,audio,videoURLs - Lesson numbers are sequential: Lessons in a chapter are numbered 1, 2, 3, ...
- Required fields present:
chapter_id,lesson_number,lesson_title,lesson_type
Common Mistakes
Mistake 1: Missing Parent References
❌ Wrong:
{
"lesson_title": "Family Vocabulary"
}
✅ Correct:
{
"chapter_id": "550e8400-e29b-41d4-a716-446655440001",
"lesson_number": 1,
"lesson_title": "Family Vocabulary"
}
Mistake 2: Wrong Content Type
❌ Wrong:
{
"lesson_type": "json_content",
"content_url": "https://www.youtube.com/watch?v=..."
}
✅ Correct:
{
"lesson_type": "url_content",
"content_url": "https://www.youtube.com/watch?v=...",
"content_type": "video"
}
Mistake 3: Using Old vocabulary_ids Format
❌ Wrong:
{
"content_json": {
"type": "vocabulary",
"vocabulary_ids": ["550e8400-e29b-41d4-a716-446655440020"]
}
}
✅ Correct:
{
"content_json": {
"type": "vocabulary",
"words": ["mother", "father", "sister"]
}
}
Explanation: Use words array instead of vocabulary_ids. System will automatically lookup words in Vocab table when rendering.
Mistake 4: Using Old grammar_ids Format
❌ Wrong:
{
"content_json": {
"type": "grammar",
"grammar_ids": ["550e8400-e29b-41d4-a716-446655440030"]
}
}
✅ Correct:
{
"content_json": {
"type": "grammar",
"grammar_points": ["Present Simple"],
"sentences": ["I eat an apple", "She eats an apple"]
}
}
Explanation: Use grammar_points or sentences instead of grammar_ids. System will find matching patterns in Grammar table.
Mistake 5: Missing Content Type
❌ Wrong:
{
"content_json": {
"exercises": [...]
}
}
✅ Correct:
{
"content_json": {
"type": "vocabulary",
"exercises": [...]
}
}
Mistake 5: Inconsistent Type Fields
❌ Wrong:
{
"lesson_content_type": "vocabulary",
"content_json": {
"type": "grammar",
...
}
}
✅ Correct:
{
"lesson_content_type": "vocabulary",
"content_json": {
"type": "vocabulary",
...
}
}
AI Integration Tips
Planning
- Plan the hierarchy first: Subject → Chapters → Lessons
- Use simple word and sentence arrays: No need to create Vocab/Grammar entries first!
- Use sequential numbering: Lesson numbers should be sequential within each chapter
Word Lists
- For vocabulary lessons: Use simple arrays like
["mother", "father", "sister"] - System auto-lookup: System will automatically search for these words in
Vocabtable when rendering - Graceful fallback: If a word doesn't exist in database, system will handle it gracefully
Sentences
- For grammar lessons: Use sentence arrays like
["I eat an apple", "She eats an apple"] - Grammar points: Or use grammar names like
["Present Simple"] - System matching: System will find matching grammar patterns in
Grammartable
Consistency
- Keep
lesson_content_typeandcontent_json.typeconsistent: They should match - Use appropriate exercise types: Match exercise types to lesson content (e.g.,
listen_repeatfor phonics)
Exercises
- Include diverse exercise types: Use multiple exercise types for better engagement
- Provide answer options: For
fill_blankandmultiple_choice, include 3-5 options - Add multimedia: Include
audio,image,videoURLs for richer learning experience
Multimedia
- Provide audio for pronunciation: Especially important for vocabulary and phonics lessons
- Use images for vocabulary: Visual aids improve retention
- Test URLs before saving: Ensure all media URLs are accessible
No IDs Needed!
⚠️ IMPORTANT: You do NOT need to create Vocab or Grammar entries before creating lessons!
- ✅ Just use word lists:
["mother", "father"] - ✅ Just use sentences:
["I eat an apple"] - ✅ System will lookup content when needed
- ❌ Don't use
vocabulary_idsanymore - ❌ Don't use
grammar_idsanymore
API Guide Endpoint
Endpoint: GET /api/learning-content/guide
Purpose: Returns this guide in JSON format for AI consumption
Response:
{
"success": true,
"data": {
"guide_version": "1.0.0",
"hierarchy": {...},
"subject_structure": {...},
"chapter_structure": {...},
"lesson_structure": {...},
"lesson_content_types": {...},
"exercise_types": {...},
"api_workflow": {...},
"validation_checklist": [...],
"common_mistakes": [...],
"ai_tips": {...}
}
}
Usage:
const guideRes = await axios.get(`${API_URL}/learning-content/guide`);
const guide = guideRes.data.data;
// Access guide sections
console.log(guide.hierarchy);
console.log(guide.lesson_content_types.vocabulary_lesson);
console.log(guide.api_workflow);
Summary
This guide provides:
- Complete hierarchy understanding: Subject → Chapter → Lesson
- 4 lesson content types: Vocabulary, Grammar, Phonics, Review
- 8 exercise types: Match, Fill Blank, Multiple Choice, Arrange Words, Listen Repeat, Identify Sound, True/False, Mixed Quiz
- API workflow: Step-by-step guide to create learning content
- Code examples: JavaScript examples for common operations
- Validation checklist: Ensure data quality before creation
- Common mistakes: Learn from typical errors
- AI integration tips: Best practices for AI-driven content creation
Next Steps:
- Review the guide
- Understand the hierarchy
- Create vocabulary and grammar entries
- Create lessons with proper content structure
- Validate all data before saving
- Test with small datasets first
For Questions:
- API Guide:
GET /api/learning-content/guide - Vocab Guide:
GET /api/vocab/guide - Grammar Guide:
GET /api/grammar/guide - Story Guide:
GET /api/stories/guide
Version: 1.0.0
Last Updated: 2024
Maintained by: SENA Learning Platform