English · Español
Teoría 04 — UX¶
🇪🇸 La interfaz tiene tres personas (estudiante, profesor, invitado) y cuatro pantallas que cubren el 95% del uso. Sin React, sin SPA, sin diseño visual heroico —
mkdocs-materialya renderiza la mayor parte; el portal añade la capa interactiva mínima. La regla: ningún componente vive sin un caso de uso que lo justifique en menos de una frase.
Los principios¶
La UX del portal existe para servir cuatro interacciones, en orden de frecuencia:
- Leer una página de teoría o de lab.
- Escribir una entrada de journal o una nota.
- Responder una pregunta de quiz o de examen.
- Repasar una tarjeta de repetición espaciada (spaced repetition).
Todo lo demás es cola larga. El presupuesto de diseño — el tiempo de Borja y el alcance del currículo — se gasta en esos cuatro. Las funciones terciarias (admin, dashboard de progreso, toggle de locale) reciben justo la UI suficiente para ser usables, no encantadoras.
La elección del framework se desprende de esto: HTML renderizado en el servidor con un toque de JS vanilla. Sin React (anti-objetivo §10 en espíritu; el coste del framework SPA no se justifica a esta escala). Sin Vue. Sin HTMX (interesante pero una dependencia nueva). El editor de markdown es el único componente significativo del lado del cliente, y es un drop-in de terceros.
Layout¶
Cada página autenticada tiene el mismo chrome:
+--------------------------------------------------------------+
| LYNX CORTEX | Curriculum Journal Notes Quizzes Progress |
| | [Admin] Logout 🇪🇸 / 🇬🇧 |
+--------------------------------------------------------------+
| | | |
| Side | Main pane | Right rail |
| bar | | (theory |
| (40 | Rendered markdown | pages only) |
| phas- | + inline annotations | |
| es) | | |
| | | |
+--------------------------------------------------------------+
| Footer: build sha · phase · last sync · status indicator |
+--------------------------------------------------------------+
- Nav superior. Seis enlaces más control de admin, logout, toggle de locale. La bandera de locale es un botón; al clicarlo se cambia
students.localey se vuelve a renderizar el chrome. - Sidebar. El árbol de 40 fases. La fase actual resaltada. Aparece un glifo de check junto a las fases con
progress.status = 'done'. Las fases son clicables; navegan al README de la fase en el panel principal. - Panel principal. El trabajo ocurre aquí. Renderiza markdown (de
docs/phase-NN-*/), entradas de journal, notas, prompts de quiz, prompts de examen. Ancho limitado a ~80ch para legibilidad. - Right rail. Solo en páginas de teoría. Muestra las notas del learner en esta página, el siguiente quiz a hacer, las tarjetas de revisión pendientes. Vacío en cualquier otra vista.
- Footer. Señal barata de estado: SHA de git del build desplegado, fase actual, timestamp de la última sincronización, un punto de estado verde/amarillo/rojo.
Las cuatro pantallas¶
Pantalla 1: Página de teoría (la vista más común)¶
+--------------------------------------------------------------+
| LYNX CORTEX | Curriculum* Journal Notes Quizzes ... |
+--------------------------------------------------------------+
| > Phase 32 | | |
| theory | # 02 — Grammar tutor agent loop | Notes |
| 00 | | on this|
| 01 | > 🇪🇸 El bucle del agente lee una | page: |
| ▶ 02 | > frase, identifica el verbo... | |
| 03 | | "Why |
| labs | ## The loop | ‘ate’ |
| | | not |
| | The grammar tutor reads an English | ‘eated’|
| | sentence, tokenizes it, applies the | -- §4 |
| | conjugation classifier, and... | |
| | | +new |
| | [+ add a note here] | |
| | | --- ---|
| | ```python | Next |
| | def conjugate(verb, tense, person) | quiz: |
| | ``` | "Past |
| | | simple |
| | ... | irreg." |
| | | |
| | | --- ---|
| | | Due |
| | | review:|
| | | 3 |
| | | cards |
+--------------------------------------------------------------+
La acción [+ add a note here] es la única interactividad inline. Al clicar se abre un editor inline anclado a ese párrafo. Al guardar, se inserta una fila en notes con page_path = '/docs/phase-32/theory/02-grammar-tutor.md' y la nota aparece en el right rail.
El right rail es densamente informativo: notas de la página, siguiente quiz, revisiones pendientes. El espacio vacío en el right rail señala "aquí estás al día" — también útil.
Pantalla 2: Journal¶
+--------------------------------------------------------------+
| LYNX CORTEX | Curriculum Journal* Notes Quizzes ... |
+--------------------------------------------------------------+
| |
| Journal — Borja [ Today | Calendar ] |
| |
| 2026-05-23 (today) |
| ---------------- |
| |
| 14:30 — Started phase 32. Read the grammar tutor |
| BLUEPRINT. The "agent loop" framing finally clicked |
| after seeing the diagram in §3. Open question: how does |
| the tool registry handle locale, since the conjugator |
| takes Spanish optionally. |
| |
| 15:15 — Implemented `is_regular(verb)` from the |
| lab statement. First test passes. Second test fails on |
| "have" — turns out `have/has/had/had` is its own class. |
| Updated table. |
| |
| [ Markdown editor below ] |
| ┌─────────────────────────────────────────────────────┐ |
| │ B I H link code ``` list preview │ |
| ├─────────────────────────────────────────────────────┤ |
| │ Append a journal entry... │ |
| │ │ |
| │ │ |
| └─────────────────────────────────────────────────────┘ |
| [ Save entry ] |
+--------------------------------------------------------------+
El editor de Markdown es SimpleMDE o un drop-in similar puro en JS (sin React, sin paso de build). El portal incluye la copia vendored en static/vendor/simplemde/ para reproducibilidad — sin fetch a CDN en tiempo de ejecución.
Comportamiento: cada guardado inserta una fila en journal_entries con day = CURRENT_DATE. Dentro del mismo día, las entradas múltiples se acumulan; el renderizado las une con timestamps. Los días pasados son de solo lectura por defecto; un control "edit" por entrada dispara un modal de confirmación.
Pantalla 3: Quiz¶
+--------------------------------------------------------------+
| LYNX CORTEX | Curriculum Journal Notes Quizzes* ... |
+--------------------------------------------------------------+
| |
| Quiz: past-simple-irregular-verbs |
| Phase 32 · Question 3 of 8 · 04:12 elapsed |
| |
| ---------------------------------------- |
| |
| Conjugate "eat" in the past simple, 3rd person singular. |
| |
| Answer: [ ate ] |
| |
| [ Skip ] [ Next ] |
| |
| ---------------------------------------- |
| |
| Progress: ████████░░░░░░░░░░░░░░░░░░ 37% |
| |
+--------------------------------------------------------------+
La UI del quiz es deliberadamente mínima. Una pregunta a la vez, un único campo de respuesta, dos botones. La puntuación (por Fase 11 — se usan tokens para comparar respuestas de texto normalizadas frente a la answer key) es del lado del servidor; el cliente solo transporta texto.
Al hacer submit-all: se finaliza una fila en quiz_attempts, se calcula score_pct, la respuesta es answers_json. La siguiente vista muestra acierto/error por pregunta con un string corto de feedback extraído de la rúbrica.
Pantalla 4: Revisión¶
+--------------------------------------------------------------+
| LYNX CORTEX | Curriculum Journal Notes Quizzes Progress |
+--------------------------------------------------------------+
| |
| Today's reviews |
| ─────────────── |
| |
| Due today: 7 · Done: 0 |
| |
| Card 1 of 7 |
| |
| ┌────────────────────────────────────────────────────┐ |
| │ Past simple of "go", 1st person singular? │ |
| └────────────────────────────────────────────────────┘ |
| |
| [ Reveal answer ] |
| |
| ... |
| |
| How well did you remember? |
| [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] |
| blackout forgot hard okay good perfect |
| |
+--------------------------------------------------------------+
Esta es la superficie de repetición espaciada (teoría 05). El botón de calificación (0–5) mapea directamente al input de calidad de SM-2. La transición (mostrar prompt → revelar respuesta → calificar) es la única interacción animada del portal; todo lo demás es una transición de página.
Tres personas¶
Persona 1: Estudiante (la por defecto)¶
El estudiante es el usuario modal. Abre el portal cada mañana, ve la fase actual resaltada en el sidebar, el "Due reviews: 7" del right rail, y el hueco del journal del día vacío. Ellos:
- Pasan la mayoría del tiempo en páginas de teoría y de lab.
- Mantienen el journal como hábito por sesión.
- Intentan quizzes cuando se les indica.
- Abordan las preguntas de examen al cerrar la fase.
- Liquidan las tarjetas de revisión pendientes.
Su navegación es marcadamente vertical dentro de una fase — clican por theory 00 → 01 → 02 → labs → examen, mayormente secuencialmente.
Persona 2: Profesor / admin¶
El admin es la misma persona (Borja en el MVP), con otro sombrero. Ellos:
- Hacen onboarding a nuevos estudiantes (en sentido de schema; el MVP solo tiene a Borja).
- Revisan el progreso de otro estudiante, si en el futuro existe un learner.
- Resetean una bandera de contraseña olvidada.
- Auditan la actividad reciente del log.
La vista de admin es una página adicional, no una interfaz paralela. Se preserva el chrome de modo estudiante; un enlace Admin aparece en el nav superior cuando students.role IN ('admin', 'teacher').
+--------------------------------------------------------------+
| Admin — Students |
+--------------------------------------------------------------+
| username display_name role last_login actions |
| ---------- -------------- -------- -------------- --------- |
| borja Borja Tarrasó admin 2026-05-23 [Reset] |
| _template _template student — [Reset] |
+--------------------------------------------------------------+
| [+ Create student] |
| |
| Recent audit log |
| ---------------- |
| 14:30 login_success borja |
| 11:02 password_set borja |
| 11:01 login_success borja (must_set=true) |
| 11:00 admin_create_student borja |
+--------------------------------------------------------------+
Persona 3: Invitado¶
La persona de invitado es el compartidor de solo lectura. El currículo es público; el portal soporta un modo de navegación sin autenticar que:
- Renderiza el contenido del currículo (páginas de teoría y lab de
docs/phase-NN-*/). - Oculta journal, notas, quizzes, progreso, admin por completo.
- Muestra un banner en la barra superior: "Estás navegando como invitado. [Iniciar sesión] para llevar el progreso."
- No escribe en ninguna tabla de la DB.
El invitado es la cara pública del currículo. La ruta / para un visitante sin autenticar renderiza el mismo árbol de teoría, menos las capas personales. El objetivo social de la Fase 41 — dejar que otros learners hagan fork del currículo — depende de que esta vista funcione sin cuenta.
Toggle de locale: solo el chrome¶
El toggle 🇪🇸 / 🇬🇧 del nav superior cambia el chrome de la UI (etiquetas del nav superior, texto de botones, texto del footer) entre inglés y español. Las páginas de teoría conservan su prosa bilingüe por §0.6 de CLAUDE.md — el bloque de resumen en español > 🇪🇸 ... al inicio de cada página de teoría es parte del contenido, no de la UI.
Por qué separar chrome y contenido: la teoría es bilingüe por diseño; el chrome es una preocupación de localización. Localizar el chrome con un diccionario de 30 strings es barato; localizar el currículo entero es justamente el objetivo del currículo.
Implementación: un filtro Jinja2 {% trans %} codificado contra students.locale, con traducciones en src/miniportal/locale/{en,es}.yaml. El número total de strings está acotado — el lab de Fase 41 lo limita a 50.
Lo que esta UX NO tiene¶
- Sin actualizaciones en tiempo real. Sin WebSocket para "nueva tarjeta pendiente"; el usuario refresca o navega.
- Sin layout específico para móvil. Lo suficientemente responsive para ser usable en un teléfono, pero no optimizado.
- Sin drag-and-drop. Reordenado de quizzes, de tarjetas, etc. — fuera de alcance.
- Sin temas. El tema por defecto de mkdocs-material es la base visual; sin framework CSS personalizado.
- Sin animaciones más allá de la revelación de tarjetas. Las transiciones de página son cargas de página.
- Sin búsqueda global. Adición futura; la búsqueda por página del navegador (Ctrl+F) basta para el MVP.
Recapitulación en un párrafo¶
Cuatro pantallas (teoría, journal, quiz, revisión) y tres personas (estudiante, admin, invitado) cubren la UX del portal. El layout es HTML renderizado en el servidor con una capa fina de JS vanilla para el editor de markdown y la revelación de tarjetas SR. El toggle de locale es solo del chrome de la UI; las páginas de teoría siguen siendo bilingües por contenido. El right rail en las páginas de teoría hace la mayor parte del trabajo de integración entre funciones: notas, siguiente quiz, revisiones pendientes — tres llamadas a la acción a una sola mirada, donde el trabajo realmente ocurre.
Siguiente: theory/05-spaced-repetition.md — derivación de SM-2, FSRS-5 como opción futura, ciclo de vida de la tarjeta.