Tipos primarios
1. slides
Presentación con elementos enriquecidos.
{
"slides": [
{
"id": "uuid",
"layout": "title_content" | "two_column" | "image_focus" | "code_demo",
"elements": [
{ "type": "heading", "text": "...", "style": {} },
{ "type": "paragraph", "text": "..." },
{ "type": "image", "mediaAssetId": "uuid" },
{ "type": "list", "items": ["..."], "ordered": true },
{ "type": "code", "language": "python", "code": "..." },
{ "type": "callout", "variant": "info|warning|tip", "text": "..." }
]
}
],
"speakerNotes": { "slide-uuid": "Notas..." }
}
Viewer: components/lesson-viewer/slide-viewer.tsx (navegación por teclado, pantalla completa, notas del presentador).
2. video
{
"source": "youtube" | "vimeo" | "upload",
"embedUrl": "https://...",
"videoUrl": "...",
"mediaAssetId": "uuid"
}
Soporta velocidad de reproducción, subtítulos, control de reproducción automática. Transcripción automática vía Whisper cuando mediaAssetId está presente.
3. pdf_viewer
{
"mediaAssetId": "uuid",
"storageUrl": "...",
"initialPage": 1
}
Viewer con react-pdf, navegación, zoom, búsqueda de texto completo.
4. rich_text
{
"html": "<h1>...</h1><p>...</p>"
}
Editor: Tiptap con extensiones (tablas, bloques de código con resaltado de sintaxis, imágenes, enlaces, color, tipografía, matemáticas). HTML sanitizado en el servidor con sanitizeHtml().
5. quiz
{
"questions": [
{ "type": "multiple_choice", "question": "...", "options": ["A","B","C","D"],
"correctIndex": 0, "explanation": "...", "concepts": ["concept-id"] },
{ "type": "true_false", "question": "...", "correctIndex": 0 },
{ "type": "fill_blank", "question": "...", "blanks": [{"answer": "..."}] },
{ "type": "matching", "pairs": [{"left": "...", "right": "..."}] },
{ "type": "ordering", "items": ["..."] },
{ "type": "numeric", "answer": 42, "tolerance": 0.1 },
{ "type": "short_answer", "acceptedAnswers": ["..."] },
{ "type": "essay", "prompt": "..." }
],
"passingScore": 70,
"configuration": {
"maxAttempts": 3,
"timeLimitMinutes": 30,
"shuffleQuestions": true,
"shuffleOptions": true,
"accessCode": "...",
"scoringPolicy": "highest" | "latest" | "average",
"reviewMode": "after_submit" | "after_due_date" | "never"
}
}
Detalles en Quiz Engine.
6. assignment
{
"instructions": "...",
"dueDate": "2026-06-15",
"maxScore": 100,
"submissionType": "text" | "file" | "both",
"rubricId": "uuid"
}
Las entregas se almacenan en el bucket privado submissions/{tenantId}/{courseId}/{lessonId}/{userId}/ (regla crítica 122).
7. live_class
{
"liveClassId": "uuid"
}
La entidad LiveClass tiene proveedor (BBB/Zoom/Teams/Meet), URL de acceso, URL de grabación. Detalles en Clases en Vivo.
8. external_link
{
"url": "https://...",
"description": "...",
"openInNewTab": true
}
Subtipos interactivos
Cuando lesson.subtype !== null, se renderiza un viewer interactivo dedicado:
interactive_video
Video con checkpoints (preguntas obligatorias antes de continuar).
{
"videoUrl": "...",
"checkpoints": [
{ "timestampSec": 120, "question": { ... } }
]
}
drag_drop
{
"items": [{ "id": "1", "label": "Mitosis" }],
"targets": [{ "id": "a", "label": "División celular", "acceptedItemIds": ["1"] }]
}
fill_blanks
{
"text": "La capital de Francia es {{0}} y se encuentra en el continente {{1}}.",
"blanks": [
{ "id": 0, "acceptedAnswers": ["París"] },
{ "id": 1, "acceptedAnswers": ["Europa", "europeo"] }
]
}
flashcard_set
{
"cards": [
{ "id": "1", "front": "¿Cuál es el teorema de Pitágoras?", "back": "a² + b² = c²" }
],
"srsEnabled": true
}
Algoritmo SRS SM-2 modificado. Programa revisiones en StudentFlashcardReview.
timeline
{
"events": [
{ "date": "1500", "title": "Descubrimiento de Brasil", "description": "..." }
]
}
Línea de tiempo interactiva con zoom.
branching_scenario
Árbol de decisión para simulaciones (ej: caso clínico, dilema ético, negociación).
{
"rootNodeId": "n1",
"nodes": {
"n1": {
"text": "Eres un médico atendiendo a un paciente con dolor torácico...",
"choices": [
{ "text": "Solicitar ECG", "nextNodeId": "n2" },
{ "text": "Internar inmediatamente", "nextNodeId": "n3" }
]
}
}
}
Editores (Lesson Builder)
Cada tipo tiene un editor visual dedicado en components/lesson-builder/:
- slides →
slides-editor.tsx(reordenamiento con dnd-kit, elementos drag-drop) - rich_text →
rich-text-editor.tsx(Tiptap) - quiz →
quiz-editor.tsx(con selector de banco de preguntas + diálogo de guardado) - assignment →
assignment-editor.tsx(selector de rúbrica, fecha de entrega) - video →
video-editor.tsx(selección de fuente + embed) - pdf →
pdf-editor.tsx(subida + selector de medios) - live_class →
live-class-editor.tsx(selección de proveedor + programación) - external_link →
external-link-editor.tsx - subtipos interactivos → editores dedicados en
components/interactive/
Limitaciones
- Quiz tipo essay sin corrección automática nativa — el administrador puede habilitar LLM grading (costo adicional)
- Los subtipos interactivos no migran a H5P — formato propio de Studeia
- Branching_scenario máximo 10 niveles de profundidad — protección contra bucles infinitos