ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Plataforma educativa abierta con IA para estudiantes de colegio público en Costa Rica.
Translation pending
EducationTypeScript · PLpgSQLGitHub @chavesgabriel012-svgOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Plataforma educativa abierta con IA para estudiantes de colegio público en Costa Rica (MVP: III Ciclo — 7.º, 8.º y 9.º). Antes se llamaba Edukemonos; la mascota y tutor, Kemo, conserva el nombre original. Guía de marca: docs/brand.md. Eduka es una iniciativa independiente. No es una plataforma oficial del Ministerio de Educación Pública. • Alcance y reglas: docs/SPEC.md • Plan por fases, riesgos y preguntas abiertas: PLAN.md • Qué contienen realmente las fuentes del MEP: docs/sources-inventory.mdRead the full README ↗
Plataforma educativa abierta con IA para estudiantes de colegio público en Costa Rica (MVP: III Ciclo — 7.º, 8.º y 9.º).
Antes se llamaba Edukemonos; la mascota y tutor, Kemo, conserva el nombre original. Guía de marca:
docs/brand.md.
Eduka es una iniciativa independiente. No es una plataforma oficial del Ministerio de Educación Pública.
docs/SPEC.mdPLAN.mddocs/sources-inventory.mdapps/web Next.js 16 (App Router, TS), Tailwind v4 + shadcn/ui
packages/ai Capa de IA intercambiable (Anthropic / OpenAI), registro de uso, prompts versionados
packages/curriculum Tipos y esquema del manifiesto de fuentes
scripts/ingest Programas de estudio oficiales del MEP: manifiesto (sources.json), descarga respetuosa, verificación
supabase/migrations Esquema, funciones y RLS
supabase/tests Pruebas de RLS contra Postgres (intentan romper cada política)
config/ help-resources.json (lo completa el fundador con números verificados)
corepack enable)TEST_DATABASE_URL)pnpm install
cp .env.example apps/web/.env.local # complete los valores
pnpm dev # http://localhost:3000
Todas están documentadas en .env.example. Lo importante:
| Variable | Para qué |
|---|---|
NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY | Cliente de Supabase en el navegador |
SUPABASE_SERVICE_ROLE_KEY | Solo servidor y scripts. Nunca en el navegador |
AI_PROVIDER | anthropic u openai |
ANTHROPIC_API_KEY | Clave de Anthropic. En sesiones de Claude Code en la nube use EDUKEMONOS_ANTHROPIC_API_KEY: la plataforma retira ANTHROPIC_API_KEY del entorno |
MODEL_BULK, MODEL_TUTOR, MODEL_VERIFY | Identificadores de modelo. No están en el código: tómelos de la documentación vigente del proveedor |
AI_PRICES_JSON | Precios por modelo para estimar costos en ai_usage |
RETENTION_DAYS_CHAT | Días que se guardan las conversaciones con el tutor (30 por defecto; pendiente de revisión legal). Las borra cada día /api/cron/purge |
CRON_SECRET | Secreto de Vercel Cron para /api/cron/purge; sin él, la limpieza diaria no corre |
eval "$(supabase/tests/start-local-pg.sh)" # Postgres desechable en el puerto 54329
pnpm lint && pnpm typecheck && pnpm test
pnpm test:rls corre solo las pruebas de RLS. Crean una base nueva, aplican un shim mínimo de Supabase (supabase/tests/supabase-shim.sql: roles anon/authenticated/service_role, auth.uid()), todas las migraciones y la semilla, y luego actúan como cada rol.
pnpm exec supabase link --project-ref <ref>
pnpm exec supabase db push # aplica supabase/migrations
psql "$DATABASE_URL" -f supabase/seed.sql
Después de crear su cuenta de correo en la app, conviértase en admin desde el SQL editor:
update public.profiles set role = 'admin' where id = '<su user id>';
Puntos de diseño:
cycles, grades, subjects): sumar I/II Ciclo es insertar filas.join_section(código, nombre, consentimiento).submit_attempt().La app vive en apps/web dentro de un monorepo pnpm. En Project Settings → Build and Deployment:
| Ajuste | Valor |
|---|---|
| Root Directory | apps/web |
| Include files outside the root directory | Activado (por defecto) — necesario para el workspace |
| Framework Preset | Next.js (se detecta solo con el Root Directory correcto) |
| Install / Build / Output | Sin override |
| Node.js Version | 22.x |
Si Root Directory queda en la raíz del repo, Vercel no encuentra next en package.json, trata el proyecto como estático y falla con "No Output Directory named "public" found".
Variables de entorno: las de .env.example (las de Supabase e IA son necesarias a partir de la Fase 1; la página inicial no las usa).
pnpm sources:verify # comprueba que los 6 programas del manifiesto siguen disponibles
El cliente respeta robots.txt, se identifica y espera ~2,5 s entre peticiones al mismo dominio.
Requiere pdftotext (poppler-utils) y las variables de Supabase e IA. Lee apps/web/.env.local si existe.
pnpm ingest db-check # ¿están las tablas?
pnpm ingest structure --source mep-prog-matematicas --grade 7 # muestra el costo estimado, NO gasta
pnpm ingest run --source mep-prog-matematicas --grade 7 --yes # descarga, extrae, estructura y carga
Extraer, no inventar: cada habilidad, contenido y extracto que propone la IA se verifica textualmente contra la página citada. Lo que no aparece queda marcado "por verificar" y la unidad no se puede publicar hasta corregirlo.
Todo entra como borrador. Volver a correr reemplaza los borradores de ese programa y grado, pero nunca toca unidades revisadas o publicadas.
pnpm ingest coverage … lista las páginas del grado que ninguna unidad cita, para revisarlas.
En Español el programa no trae habilidades específicas: sus criterios de evaluación se cargan como habilidades, cada uno con la página donde aparece textualmente.
Solo para unidades publicadas. Requiere la migración 20261003000100_content_generation.sql.
pnpm content generate --subject matematicas --grade 7 # muestra el costo estimado, NO gasta
pnpm content generate --subject matematicas --grade 7 --yes # genera, verifica y carga como borrador
pnpm content publish --subject matematicas --grade 7 # publica solo lo que pasó todas las verificaciones
pnpm content status --subject matematicas --grade 7
Por unidad se generan resumen, explicación paso a paso, ejemplos resueltos, glosario y unos 3 ítems por habilidad (entre 6 y 12). En Español se agregan ítems de lectura inferencial y crítica y 2 consignas de escritura.
MODEL_VERIFY busca errores conceptuales, de cálculo y contenido fuera de la unidad. Si encuentra uno, ese material no se publica.MODEL_VERIFY resuelve cada ítem sin ver la respuesta. Si la respuesta es un cálculo, además se recalcula con mathjs, y debe coincidir con la opción marcada y solo con ella. verified = true solo si todo coincide. Solo los ítems verificados entran al diagnóstico.publish deja lo publicado como "Generado con IA · pendiente de revisión". En /revisar/<unidad>/contenido un revisor lo aprueba (pasa a "revisado por docente"), lo edita o lo rechaza.pnpm content repair corrige el material que la revisión retuvo: lo reescribe con los problemas señalados y lo vuelve a revisar antes de publicarlo.generate salta las unidades que ya tienen material en Supabase: un fallo, el fusible de gasto o un contenedor reciclado nunca hacen pagar dos veces.Sin registro: el estudiante elige año → materia → unidad (/estudiar/7/matematicas, /unidad/<id>) con pestañas Aprender, Practicar y Preguntar al tutor (Fase 4). La primera vez que responde, recibe una sesión anónima de Supabase que guarda su avance en ese dispositivo.
submit_attempt) y muestra por qué cada opción es correcta o no. Si no se puede abrir sesión (por ejemplo, el límite por IP de Supabase en un colegio), igual califica con check_answer, sin guardar, y lo avisa./estudiar/<año>/<materia>/diagnostico): 10 preguntas verificadas que se adaptan a las respuestas; nivel de 1 a 5 y ruta sugerida. Algoritmo y justificación: docs/diagnostic.md./unirme): código + nombre + consentimiento. El nombre nunca va a la IA.Configuración necesaria en Supabase: Authentication → Sign In / Providers → activar Allow anonymous sign-ins. Conviene subir el límite de inicios anónimos por IP (Authentication → Rate Limits) para que una clase entera, detrás de una sola IP, pueda guardar su avance.
Pestaña Preguntar al tutor de cada unidad (POST /api/tutor, respuesta en streaming). Modelo: MODEL_TUTOR.
packages/ai/src/prompts/tutor.ts.mathjs) para toda operación en Matemáticas.config/help-resources.json) y le indican al tutor responder con cuidado.TUTOR_MAX_MESSAGES_PER_SESSION y TUTOR_MAX_MESSAGES_PER_DAY (contadores en Postgres), máximo de tokens por respuesta y el fusible de gasto.ai_usage guarda los tokens de caché aparte y el costo usa la tarifa real.writing_feedback). Límite WRITING_FEEDBACK_MAX_PER_DAY (20).Evaluaciones: pnpm eval:tutor (sin --yes solo estima) corre 60 casos (packages/ai/evals/tutor/cases.json) y escribe el reporte en docs/evals/.
Variables necesarias en el servidor (Vercel): SUPABASE_SERVICE_ROLE_KEY, ANTHROPIC_API_KEY, AI_PROVIDER, MODEL_TUTOR, MODEL_BULK, MODEL_VERIFY, AI_PRICES_JSON, AI_BUDGET_DAILY_USD, AI_BUDGET_MONTHLY_USD, TUTOR_MAX_MESSAGES_PER_SESSION, TUTOR_MAX_MESSAGES_PER_DAY, CRON_SECRET (limpieza diaria de conversaciones).
/docente: presentación del panel para quien no ha entrado; con sesión, las secciones del docente y el formulario
para crear una. Cualquier cuenta de correo (no anónima) es docente. Al entrar con el enlace del correo se llega aquí./docente/demo: sección de demostración sin necesidad de cuenta, con 26 estudiantes ficticios sobre los temas
reales de 7.º, etiquetada como tal. Los datos son deterministas (buildDemoSection en packages/curriculum) y el
dominio sale del mismo algoritmo que usa la práctica real./docente/seccion/<id>: código para dictar (copiar, cambiar, desactivar), indicadores, hallazgos con «¿Cómo se
calculó?», resumen con IA, estudiantes que podrían necesitar apoyo, mapa de calor estudiantes × temas, actividad,
diagnóstico, errores de escritura, temas consultados a Kemo, tabla de estudiantes y CSV. Registro de accesos al pie./docente/seccion/<id>/estudiante/<id>: detalle por estudiante (nivel por materia, dominio e intentos por tema,
errores de escritura, línea de tiempo) y la opción de sacarlo de la sección.teacher_audit_log.computeSectionMetrics en packages/curriculum/src/teacher.ts). El resumen con IA
recibe solo los hallazgos (conteos y títulos de temas, sin nombres), usa MODEL_BULK (prompt
teacher-summary-system), se guarda en teacher_summaries por hash de los hallazgos y tiene un límite de 10
generaciones por docente al día (6 para la demostración). Necesita la migración 20261007000100_teacher_panel.sql;
sin ella el panel funciona, pero el resumen no se guarda./revisar)/entrar con tu correo (enlace mágico).update public.profiles set role = 'reviewer' where id = '<user id>';/revisar eliges materia y grado. En cada unidad ves el texto de la página oficial al lado, editas, guardas (se verifica de nuevo) y la marcas como revisada, la publicas o la rechazas. Todo queda en review_log.En Supabase → Authentication → URL Configuration, agrega la URL de Vercel en Site URL y https://<tu-dominio>/auth/confirm en Redirect URLs.
import { createAI } from "@edukemonos/ai";
const ai = createAI({ sink: (row) => saveToAiUsage(row) });
const { data } = await ai.generateStructured(
{ role: "bulk", purpose: "structure_curriculum" },
{ system, messages, schema, schemaName: "units" },
);
AI_PROVIDER y los MODEL_*.MODEL_* acepta una cadena de respaldo (MODEL_TUTOR=claude-haiku-4-5,claude-sonnet-5-5): si un modelo falla, se usa el siguiente, salvo que haya rechazado el pedido (eso se respeta). Cada intento fallido queda en ai_usage.AI_BUDGET_DAILY_USD y AI_BUDGET_MONTHLY_USD (día y mes de Costa Rica). Antes de cada llamada se suma ai_usage; al llegar al tope no se llama a la IA. Si el gasto no se puede leer, la llamada se rechaza. Con tope configurado, todo modelo debe tener precio en AI_PRICES_JSON o la app no arranca.pnpm ai:diagnose prueba cada modelo configurado con una llamada mínima y muestra el gasto de hoy y del mes.packages/ai/src/prompts/ con id y versión, que se guardan junto al contenido generado.