ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Catálogo web sobre Argentina, con prosa épica de registro alto. Estado: la primera rebanada de producto está entregada. La aplicación compila, corre contra PostgreSQL y está desplegada. Existen la tabla entidad con su migración, el registro de descriptores, el módulo catalogo, seis rutas en src/app/ y la primera ficha de contenido curado (contenido/procer/manuel-belgrano.ts). /catalogo y /catalogo/[slug] se sirven contra el módulo real.README 전문 보기 ↗
Catálogo web sobre Argentina, con prosa épica de registro alto.
Estado. La aplicación compila, corre contra PostgreSQL y está desplegada. Existen dos módulos:
catalogo, con la tablaentidad, el registro de descriptores y la primera ficha curada (contenido/procer/manuel-belgrano.ts), yidentidad, con cuentas de email y contraseña o Google sobre Better Auth (ADR 0019)./catalogoy/catalogo/[slug]se sirven contra el módulo real, y/ingresary/registrarsecontraidentidad; el inicio de sesión en producción espera la configuración de sus variables (#123). Todavía no existenmoderacion,aprendizajeniprogreso: las pantallas de/ficha,/tarjetas,/quizy/quiz/resultadoson presentación con datos simulados. La arquitectura y el stack están decididos endocs/adr/.
Un catálogo de contenido sobre Argentina —próceres, monumentos, animales,
comida, fechas patrias, eventos históricos— pensado para un lector de doce
años en adelante, que lo lea, lo entienda y lo repase jugando. La audiencia y
el registro épico de la prosa están decididos en
ADR 0012; una versión
para chicos más chicos, en otra lengua y quizás otro diseño, está pospuesta,
no cancelada (ver
docs/decisiones-pendientes.md).
La idea no es un enciclopedismo: es que el contenido se pueda ver a simple vista, con una interfaz clara y sin fricción, y que arriba de ese catálogo haya tarjetas de repaso y un juego de preguntas que refuercen lo leído.
El conjunto de tipos de contenido no está cerrado a propósito. Hoy son los que están arriba; mañana pueden ser otros. Toda la arquitectura está diseñada alrededor de ese hecho: agregar un tipo nuevo tiene que ser barato (ver ADR 0001).
Las cuentas existen (ADR 0019), pero ninguna pantalla exige sesión y el
progreso todavía no se guarda. A quién se le atribuye el progreso de un
visitante, y si se reconcilia con su cuenta cuando se registra, es una decisión
abierta a propósito: la audiencia arranca a los doce años
(ADR 0012) y a esa edad se sigue siendo menor, así que persistir un
identificador por navegador sigue siendo una decisión sobre datos de menores,
no un detalle de implementación —la dimensión se aflojó con la nueva audiencia,
pero no desapareció—. Está registrada, con su disparador y su regla interina,
en docs/decisiones-pendientes.md.
usuario, admin y superadmin. Un visitante sin sesión no es un
rol: es la ausencia de sesión.Una sola aplicación fullstack, un solo deploy, organizada en cinco módulos:
| Módulo | De qué se ocupa |
|---|---|
catalogo | Entidades, tipos y sus fichas |
aprendizaje | Tarjetas de repaso y quiz |
progreso | Eventos de actividad, puntos, ligas, áreas flojas |
moderacion | Propuestas de la comunidad y su aprobación |
identidad | Cuentas, sesiones y roles |
Regla de límite, vinculante: la capa web no consulta la base de datos; le pide al módulo. Toda verificación de permisos ocurre dentro del módulo, nunca solo en la interfaz.
El catálogo se guarda en una sola tabla con un discriminador de tipo y una
columna JSONB. Los campos de cada tipo se definen en descriptores en
código, que son la fuente única para tipar la columna, validar la importación,
validar las propuestas, y renderizar el formulario y la ficha.
El contenido curado se escribe en archivos versionados en este repositorio y un script lo importa a la base, que es lo que sirve la aplicación. Así el contenido tiene historial, revisión y vuelta atrás, sin construir nada.
| Capa | Tecnología |
|---|---|
| Framework | Next.js 16 · React 19 · TypeScript |
| Estilos | Tailwind CSS v4 |
| Base de datos | PostgreSQL |
| Acceso a datos | Drizzle ORM |
| Validación | Zod |
| Tests | Vitest |
| Hosting | Vercel |
| Base gestionada | Neon |
| Autenticación | Better Auth (ADR 0019) |
El criterio de selección fue explícito: lo mejor para el proyecto, no lo más conocido ni lo más novedoso. El razonamiento completo, con las alternativas que se descartaron y por qué, está en ADR 0003.
Requisitos: Node 22 (fijado en .nvmrc), pnpm y Docker.
git clone https://github.com/luciano-stefano-meloclaps/platform-argentum.git
cd platform-argentum
pnpm install
cp .env.example .env # completar DATABASE_URL y DATABASE_URL_UNPOOLED
docker compose up -d # PostgreSQL 18 local
pnpm db:migrate # aplica las migraciones
pnpm contenido:importar # carga el contenido curado en la base local
pnpm dev # http://localhost:3000
Los valores de la base local salen de docker-compose.yml. El archivo es .env
—no .env.local—: es el que leen pnpm db:ping y drizzle.config.ts.
Ojo: en Next.js, .env.local pisa a .env. Si existe un .env.local, la
aplicación (pnpm dev, pnpm build) usa sus valores y no los de .env, aunque
pnpm db:migrate y drizzle.config.ts sigan leyendo .env. Si la aplicación y
las migraciones parecen apuntar a bases distintas, mirá primero si hay un
.env.local olvidado.
El módulo identidad (Better Auth, ADR 0019) necesita BETTER_AUTH_SECRET,
BETTER_AUTH_URL, GOOGLE_CLIENT_ID y GOOGLE_CLIENT_SECRET. Se leen en el
primer uso, no al compilar: pnpm build no las exige, pero la primera petición
que las necesite falla con un error que nombra la que falta. En Vercel se
cargan en los tres entornos (Production, Preview y Development), con
BETTER_AUTH_SECRET y BETTER_AUTH_URL distintos por entorno, y el URI de
redirección <BETTER_AUTH_URL>/api/auth/callback/google registrado en Google
Cloud Console por cada URL. El detalle, sin valores reales, está en
.env.example.
| Comando | Qué hace |
|---|---|
pnpm dev | Servidor de desarrollo |
pnpm build | Compila para producción |
pnpm typecheck | next typegen y tsc --noEmit |
pnpm lint | ESLint |
pnpm test | Tests con Vitest |
pnpm db:ping | Verifica que la base responda |
pnpm db:generate | Genera migraciones a partir del esquema |
pnpm db:migrate | Aplica las migraciones pendientes |
pnpm contenido:importar | Importa contenido/ a la base, validando cada ficha contra el descriptor de su tipo (ADR 0004) |
pnpm desplegar:datos | db:migrate y después contenido:importar. Contra una base que no sea local exige DB_CONFIRMAR_DESTINO=<host> (ADR 0023); el procedimiento está en docs/runbooks/desplegar-datos.md |
Antes de dar por terminado un cambio: pnpm typecheck && pnpm lint && pnpm test.
Las pruebas de catalogo corren contra el PostgreSQL de Docker: sin
docker compose up -d, fallan con ECONNREFUSED.
El contenido vive en contenido/<tipo>/<slug>.ts: un archivo TypeScript por
entidad, tipado por el descriptor de su tipo
(ADR 0009). El directorio es el
tipo y el nombre del archivo es el slug. La prosa va entre comillas
dobles concatenadas con +: cada tramo termina con un espacio salvo el último
del campo, un párrafo nuevo es "\n\n" y la importación no normaliza nada
(ADR 0030).
// contenido/procer/manuel-belgrano.ts
export default {
nombre: "Manuel Belgrano",
datos: {
nombreCompleto: "Manuel José Joaquín del Corazón de Jesús Belgrano",
anioDeNacimiento: 1770,
anioDeMuerte: 1820,
resumen:
"Abogado, economista y militar porteño. Creó la bandera celeste y blanca " +
"en 1812 y dedicó su vida y su fortuna a la independencia y a la escuela " +
"pública.",
semblanza:
"Manuel Belgrano no fue un militar que aprendió a gobernar: fue un " +
"sembrador obligado, contra su naturaleza y su fortuna, a defender " +
"el surco con la espada. " +
"\n\n" +
"…",
imagen: {
textoAlternativo: "Retrato de Manuel Belgrano",
credito: "Museo Histórico Nacional",
licencia: "dominio-publico",
},
},
};
Se eligió TypeScript y no Markdown ni JSON por una razón concreta: el error aparece en el editor, antes de correr nada. Las alternativas y sus trade-offs están en el ADR 0009.
La imagen va en public/contenido/<tipo>/<slug>.webp y el archivo no declara
su ruta —se deriva del tipo y del slug—, pero sí su texto alternativo, su crédito
y su licencia, que es un conjunto cerrado: una imagen sin derechos declarados
no compila.
Se abre un pull request, se revisa y se aprueba. La importación valida cada ficha contra el descriptor de su tipo: si no cumple el esquema, falla y el contenido no entra.
Por rebanadas: cada una es una funcionalidad completa —de los datos hasta la pantalla— que termina desplegada y usable por sí sola. No se construye "todo el backend" y después "todo el frontend".
Cada rebanada se corta en tickets, que son issues de este repositorio, y
nada entra al historial sin un ticket que lo explique. El trabajo lo hacen
agentes de Claude Code con roles y límites definidos en
CLAUDE.md.
El estado de cada ticket se sigue en el
tablero del proyecto
(Backlog, Listo, En curso, En revisión y Hecho). Los tickets se
clasifican con etiquetas de tipo, área y prioridad; el esquema está en
docs/agents/issue-tracker.md.
El trabajo con ticket llega a la rama development: el
delivery-specialist pushea la rama de la rebanada y abre el pull request
contra development —nunca contra main—, y lo mergea. Cada uno de esos dos
pasos, push y merge, requiere la verificación explícita del usuario antes de
ejecutarse.
Mergear development a main y desplegar sigue siendo enteramente del
usuario, en su propio tiempo.
| Ruta | Qué contiene |
|---|---|
CONTEXT.md | Glosario del dominio: el vocabulario del proyecto |
docs/adr/ | Decisiones arquitectónicas, con su contexto y sus alternativas |
docs/decisiones-pendientes.md | Lo que todavía no se decidió, con su disparador y su regla interina |
docs/runbooks/ | Operación: entornos y bases, identidad en producción, migrar e importar en producción |
docs/marca/sistema-de-diseno.md | La identidad Argentum v1.0: paleta, tipografía y reglas de aplicación |
docs/marca/sistema-de-diseno-v2.md | El giro museístico de Argentum (ADR 0015): logotipo, concepto y tipografía nuevos |
docs/tickets-del-arranque.md | El corte del arranque en diez cimientos, y su razonamiento |
Antes de proponer un cambio que contradiga una decisión registrada, leé el ADR correspondiente. Si la decisión cambia, se escribe un ADR nuevo que supersede al anterior; el viejo no se edita.
docs/agents/| Configuración de las skills de ingeniería: tracker de issues y documentación de dominio |
.claude/skills/ | Skills del proyecto: convenciones-git, revision-de-ui, voz-narrativa, investigacion-historica e identidad-argentum |
CLAUDE.md | Contexto del proyecto para Claude Code, y el equipo de agentes |