Nexu uses a singleDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Stivenz3/Nexu/llms.txt
Use this file to discover all available pages before exploring further.
questions subcollection under each lesson to store every question — both the inline quizzes embedded in theory blocks and the pool of questions drawn for the final exam. The questionType field distinguishes between them at query time. All questions live at lessons/{lessonId}/questions/{questionId}.
Two question types
questionType | Where used | How referenced |
|---|---|---|
intercalada | Embedded inside a theory block | Block’s questionId or questionIds[] field |
evaluacion_final | Final exam question pool | Fetched by fetchExamQuestions |
b04_modulo_c having three and b05_modulo_d having two) and a pool of 15 exam questions (q_e01 through q_e15).
LessonQuestion schema
Every question document — inline or exam — conforms to this shape:
| Field | Type | Description |
|---|---|---|
questionId | string | Unique ID, e.g. q_p1i or q_e01 |
blockRef | string | blockId of the block this question belongs to |
questionType | 'intercalada' | 'evaluacion_final' | Determines where the question is used |
order | number | Display order within the question pool |
text | string | Full question text shown to the learner |
options | QuestionOption[] | Answer choices (see below) |
explanation | string | Explanation shown after answering (inline) or after the exam |
normativeRef | string | Regulation reference for the correct answer |
difficulty | 'basica' | 'intermedia' | 'avanzada' | Informational label — not used for filtering in the current implementation |
QuestionOption shape
Example question (q_p1i — inline, intercalada)
Example question (q_e01 — exam pool, evaluacion_final)
Fetching exam questions — fetchExamQuestions
fetchExamQuestions filters the lesson’s questions subcollection to only evaluacion_final questions, optionally shuffles them, and returns the requested count:
fetchLessonQuestions (which fetches the entire questions subcollection) and then filters client-side:
LessonExamPage calls fetchExamQuestions(lessonId, 15, true) so each attempt presents a freshly shuffled selection from the pool.
Inline questions
Inline questions are referenced by the theory block that contains them — either viaquestionId (a single question ID string) or questionIds (an array of IDs). The helper getTheoryQuestionIds normalises both into string[]:
LessonFlowPage fetches each question by ID using fetchQuestion(lessonId, questionId) and presents them sequentially via InlineQuestionView. The learner must answer every inline question correctly to mark the theory block as completed and unlock the next block.
Exam flow
The full exam lifecycle from gate-check to certificate issuance:Gate check — canAccessFinalExam
When the learner navigates to
If
/leccion/:id/evaluacion, LessonExamPage first calls canAccessFinalExam(userId, lessonId). This returns { allowed: boolean, reason? } with the following possible reasons if access is denied:reason | Meaning |
|---|---|
not_completed | Not all non-exam blocks are completed |
already_passed | Learner has already passed this exam |
no_progress | No progress document exists yet |
no_exam | No exam block found in the lesson |
allowed is false, the page renders a blocked state and redirects the learner back to the lesson.Load questions
If access is allowed,
LessonExamPage calls fetchExamQuestions(lessonId, 15, true) to draw 15 randomized questions from the evaluacion_final pool. It also loads the exam block’s ExamBlockContent to read passingPercent and other configuration.Learner answers all questions
The exam renders one question at a time. The learner selects an option and clicks “Siguiente” to advance. No feedback is shown during the exam — all answers are revealed only after submission.
Score calculation
On the final question, clicking “Finalizar evaluación” calculates the score client-side: the number of correct answers divided by total questions, multiplied by 100 and rounded to the nearest integer.
Persist result — saveExamResult
saveExamResult writes the result to the learner’s lessonProgress document:type === 'exam' in the lesson’s blocks — it does not assume a fixed block ID like b08_exam. The function updates:blocksProgress[examBlockId]→{ completed: passed, lastScore: score, attempts: n, passed }status→'passed'ifscore >= passingPercent, otherwise'failed'bestEvalScore→ maximum of previous best and current scoreevalAttempts→ appended with the current scorecompletedAt→ set to server timestamp if passed
Outcome
- Score ≥
passingPercent→status: 'passed'.LessonExamPagecallstryIssueCourseCertificateAfterLesson()and navigates to/certificado. - Score <
passingPercent→status: 'failed'. The learner can click “Intentar de nuevo” to retry immediately —unlimitedAttempts: truein the current lesson seed means there is no retry limit.
Using fetchExamQuestions and saveExamResult together
The following pattern mirrors what LessonExamPage does end-to-end:
Lesson 1 question stats
| Category | Count | IDs |
|---|---|---|
Inline (intercalada) | 8 | q_p1i – q_p8i |
Exam pool (evaluacion_final) | 15 | q_e01 – q_e15 |
| Total | 23 |
difficulty field values — basica, intermedia, avanzada — are stored on each question for informational purposes. The current implementation does not use difficulty for filtering or adaptive selection; fetchExamQuestions draws uniformly from the entire pool.