ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기GlobalShapers-Valencia hub project, in collab with Geneva hub, to raise awareness about AI-generated content.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Proyecto global de Global Shapers para concienciar sobre contenido generado por IA. Fase 1: reconocimiento rápido (imagen real vs. IA). Fase 2: formación con explicaciones localizadas por hub.README 전문 보기 ↗
Proyecto global de Global Shapers para concienciar sobre contenido generado por IA. Fase 1: reconocimiento rápido (imagen real vs. IA). Fase 2: formación con explicaciones localizadas por hub.
aiwareness/
├── app/ # Next.js App Router
│ ├── page.tsx # Onboarding: año nacimiento + hub/país
│ ├── phase1/page.tsx # Modo simple/nativo digital
│ ├── results/page.tsx # Resumen de aciertos + compartir estilo Wordle
│ └── phase2/page.tsx # Módulo formativo
├── components/
│ ├── HubPicker.tsx # Selector de hub con búsqueda
│ ├── ImageCard.tsx # Tarjeta con botones grandes + swipe opcional
│ ├── ShareResults.tsx # Genera el texto de resultados para compartir
│ └── ZoomableImage.tsx # Imagen con zoom/pan táctil
├── lib/
│ ├── supabaseClient.ts
│ ├── images.ts # Resuelve URLs de imagen (Storage o local)
│ ├── hubConfig.ts # Carga el config.json de un hub concreto
│ ├── i18n.ts # Diccionario de textos de interfaz por idioma
│ ├── pendingAttempts.ts # Cola de reintento para inserts fallidos
│ ├── hubs.ts # Carga el índice de hubs generado en build
│ ├── sampling.ts # Aleatorizador: N imágenes del pool del hub
│ └── types.ts
├── content/
│ ├── manifest.json # Banco global: id -> {file, is_ai_generated}
│ └── images/ # Copia local para desarrollo sin Supabase
├── locales/
│ └── {idioma}/{hub}/config.json
│ # Cada hub NO sube imágenes propias: solo elige, por id, qué
│ # subconjunto del pool usar (phase1_pool) y añade sus textos
│ # explicativos localizados (phase2). "hub"/"label"/"country"/
│ # "language" son la ÚNICA fuente de verdad sobre qué hubs
│ # existen — no hay ninguna lista hardcodeada en el código.
├── supabase/
│ └── schema.sql # Modelo de datos completo
├── scripts/
│ ├── analyze_results.py # Estadísticas por país/hub/edad (PEP 8)
│ ├── validate-configs.js # Valida configs + referencias al manifest
│ ├── copy-locales-to-public.js # Genera hubs-index.json + assets estáticos
│ ├── sync-hubs.js # Sincroniza locales/ -> tabla "hubs"
│ ├── setup-storage.js # Crea el bucket de imágenes (una vez)
│ ├── import-hf-images.js # Descarga imágenes al azar de Hugging Face al banco
│ ├── normalize-images.js # Iguala nitidez/tamaño de las fotos reales a las de IA
│ └── upload-images.js # Sube content/images/ al bucket
├── docs/ # Fuente HTML de los documentos imprimibles
│ ├── one-pager.html # -> AIwareness-Global-Shapers-Valencia.pdf
│ ├── hub-onboarding-guide.html # -> AIwareness-Hub-Onboarding-Guide.pdf
│ └── build-pdfs.sh # Regenera los dos PDF desde su HTML
├── AIwareness-Global-Shapers-Valencia.pdf # Generado con docs/build-pdfs.sh
├── AIwareness-Hub-Onboarding-Guide.pdf # Generado con docs/build-pdfs.sh
└── .env.example
En vez de que cada hub suba y mantenga su propio set de imágenes, hay
un único banco compartido, con la verdad sobre cada imagen (¿es real
o generada por IA?) centralizada en content/manifest.json:
{
"img001": { "file": "images/img001.jpg", "is_ai_generated": true }
}
Las imágenes en sí viven en Supabase Storage (bucket público
aiwareness-images), no en el repositorio — así el banco puede crecer
sin inflar el clon de git y sin necesitar un redeploy para publicar
contenido nuevo. lib/images.ts resuelve la ruta del manifest a la URL
pública del bucket; en local, si no hay un proyecto de Supabase
configurado, cae automáticamente a servir las imágenes que tengas en
content/images/ como assets estáticos (modo solo-interfaz, ver más
abajo).
Cada hub, en su config.json, simplemente declara qué subconjunto de
ese banco es culturalmente relevante para su región y cuántas se
muestran por sesión:
{
"phase1_pool": ["img001", "img002", "img003", "..."],
"phase1_sample_size": 10
}
En cada partida, lib/sampling.ts elige aleatoriamente
phase1_sample_size imágenes de ese phase1_pool. Así, con un banco de
(por ejemplo) 50 imágenes, cada usuario ve una combinación distinta de
10, y un hub puede tener un pool de 50 mientras otro usa solo 15 de esas
mismas imágenes si son las que le resultan relevantes.
No hay ninguna lista de hubs escrita a mano en el código. La carpeta
locales/{idioma}/{hub}/config.json es la única fuente de verdad:
scripts/copy-locales-to-public.js recorre todos los
config.json y genera public/content/hubs-index.json. El selector
de hub del onboarding (app/page.tsx) lo carga vía lib/hubs.ts.scripts/sync-hubs.js hace el mismo recorrido y sincroniza
(upsert) la tabla hubs de Supabase, para que los insert en
participants/attempts no fallen por la foreign key. Se ejecuta
automáticamente al fusionar cambios en locales/** sobre main (ver
.github/workflows/sync-hubs.yml) — añadir un hub nuevo no requiere
ningún paso manual en Supabase ni tocar código.supabase/schema.sql. Esto
crea las tablas participants, attempts y hubs (esta última la
rellena scripts/sync-hubs.js automáticamente, no hace falta insertar
filas a mano).Project URLanon public keyservice_role key (solo para scripts de mantenimiento, nunca para el
frontend)SUPABASE_URL=https://tu-proyecto.supabase.co \
SUPABASE_SERVICE_ROLE_KEY=tu-service-role-key \
node scripts/setup-storage.js
Esto crea el bucket público aiwareness-images (solo hace falta una vez
por proyecto).content/images/:
SUPABASE_URL=... SUPABASE_SERVICE_ROLE_KEY=... node scripts/upload-images.js
Repite este paso cada vez que se añadan imágenes nuevas al banco.globalshapers/aiwareness.SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY (los
mismos valores del paso A.3). Los usa .github/workflows/sync-hubs.yml
para mantener la tabla hubs sincronizada cada vez que se fusiona un
hub nuevo — sin esto, el paso "añadir un hub" queda incompleto y los
participantes de ese hub no podrán guardar sus respuestas.locales/{idioma}/{hub}/ con su
config.json vía Pull Request (ver sección 4). .github/workflows/ci.yml
corre lint + build en cada PR; validate.yml valida el contenido de
locales/; sync-hubs.yml sincroniza Supabase al fusionar a main;
keep-supabase-awake.yml hace un ping diario a la API de Supabase para
que el proyecto gratuito no se pause por inactividad.En https://vercel.com, Add New → Project e importa el repo de GitHub.
Framework preset: Next.js (detectado automático).
En Environment Variables añade:
NEXT_PUBLIC_SUPABASE_URL = Project URL de SupabaseNEXT_PUBLIC_SUPABASE_ANON_KEY = anon public key de SupabaseNo añadas aquí la service_role key: no la usa la app, solo los
scripts de scripts/.
Deploy. Cada push a main vuelve a desplegar automáticamente.
(Opcional) Configura un dominio propio en Project Settings → Domains,
por ejemplo aiwareness.globalshapers.org.
Antes de anunciar el lanzamiento, haz una prueba real de extremo a
extremo: completa el onboarding en el sitio desplegado y confirma en
Supabase (Table Editor) que aparece la fila en participants. Si
falla, lo más probable es que el hub elegido no esté aún en la tabla
hubs (revisa que sync-hubs.yml se haya ejecutado correctamente).
npm install
cp .env.example .env.local # rellena con tus claves de Supabase
npm run dev
Modo solo-interfaz (sin Supabase): si aún no tienes un proyecto de
Supabase, puedes saltarte el paso de rellenar .env.local y ejecutar
npm run dev igualmente. La app detecta que faltan las credenciales y
navega por todo el flujo (onboarding, fase 1, resultados, fase 2) sin
guardar nada en base de datos, sirviendo las imágenes desde
content/images/ en vez de Supabase Storage — ideal para revisar diseño
y UX antes de tener el backend listo. Verás un aviso en la consola del
navegador recordándolo.
Caso A — usar imágenes que ya existen en el banco compartido:
locales/es/valencia-hub/config.json como plantilla dentro de
locales/{tu-idioma}/{tu-hub}/config.json, rellenando hub (debe
coincidir con el nombre de la carpeta), label (nombre visible en el
selector), country y language.content/manifest.json forman el
phase1_pool de tu hub y cuántas (phase1_sample_size) se muestran
por sesión.phase2 (título + explicación) en tu idioma
para las imágenes que quieras usar como material formativo..github/workflows/validate.yml comprueba automáticamente
que el JSON es válido y que todos los ids referenciados existen en el
manifest; .github/workflows/ci.yml comprueba que el build sigue
funcionando.main, .github/workflows/sync-hubs.yml da de alta el
hub en Supabase automáticamente y Vercel redespliega. No hace falta
ningún paso manual adicional.Caso B — aportar imágenes nuevas al banco compartido:
Añade las imágenes nuevas directamente a content/images/ (formato
.jpg/.png/.webp, máx. ~5MB cada una) con el siguiente id libre
del manifest. No crees subcarpetas: el script de
subida antepone images/ a la ruta, y la ruta resultante debe
coincidir con el campo file del manifest.
Añade su entrada en content/manifest.json con is_ai_generated
(true/false).
Atajo: node scripts/import-hf-images.js [--ai 50] [--real 50]
hace los pasos 1 y 2 por ti con imágenes al azar del dataset
Defactify_Image_Dataset
(Roy et al., 2026): las reales son fotos de MS COCO y las de IA son solo
de Midjourney 6 (Label_B = 5). Las descarga a content/images/ con el
siguiente id libre y las registra en el manifest, sin repetir la misma
escena (caption) entre reales e IA. Las fotos reales se normalizan al
guardarlas (recorte cuadrado, 436×436, nitidez y compresión como las de
IA, ver scripts/normalize-images.js) para que no se distingan por
calidad en vez de por contenido. Aun así, revisa las imágenes a
ojo (etiqueta correcta, nada inadecuado ni con personas
identificables) antes de subirlas; para descartar una, borra el archivo
y su línea del manifest.
Referencia esos nuevos ids desde tu config.json como en el Caso A.
Otros hubs también podrán usarlas si les resultan relevantes.
Tras fusionar el PR, quien mantenga el proyecto ejecuta
node scripts/upload-images.js (con la service_role key) para
subir las imágenes nuevas al bucket (si sobrescribe imágenes ya
publicadas, sube también IMAGE_BANK_VERSION en lib/images.ts para
saltarse la caché de imágenes) — este paso no está automatizado
en CI a propósito, porque requiere una clave que no debe exponerse a
Pull Requests externos.
scripts/analyze_results.py se conecta a Supabase con la service_role key (nunca la expongáis en el frontend) y exporta a CSV la tasa de
acierto por país, hub, fase y franja de edad. Requiere Python 3.10+:
pip install supabase pandas
export SUPABASE_URL=...
export SUPABASE_SERVICE_ROLE_KEY=...
python scripts/analyze_results.py
app/page.tsx).AIwareness-Global-Shapers-Valencia.pdf (one-pager) y
AIwareness-Hub-Onboarding-Guide.pdf (guía para nuevos hubs) se generan a
partir del HTML en docs/. Para regenerarlos tras editar el HTML:
bash docs/build-pdfs.sh
Necesita Microsoft Edge o Chrome instalado (imprime a PDF en modo headless);
las fuentes y logos usados están en docs/assets/, así que funciona sin
conexión.
Las imágenes del banco importadas con scripts/import-hf-images.js
proceden del Defactify_Image_Dataset
de Hugging Face: fotos reales de MS COCO e imágenes generadas con
Midjourney 6. Muchas gracias a Rajarshi Roy y a todo el equipo que lo
creó y lo publicó en abierto. Si usas estos datos, cita el artículo:
@misc{roy2026comprehensivedatasethumanvs,
title={A Comprehensive Dataset for Human vs. AI Generated Image Detection},
author={Rajarshi Roy and Ashhar Aziz and Shashwat Bajpai and Nasrin Imanpour and Gurpreet Singh and Shwetangshu Biswas and Kapil Wanaskar and Parth Patwa and Subhankar Ghosh and Shreyas Dixit and Nilesh Ranjan Pal and Vipula Rawte and Ritvik Garimella and Amitava Das and Amit Sheth and Gaytri Jena and Vasu Sharma and Aishwarya Naresh Reganti and Vinija Jain and Aman Chadha},
year={2026},
eprint={2601.00553},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2601.00553},
}
El dataset no declara licencia en su ficha de Hugging Face, y las fotos reales provienen de MS COCO (imágenes de Flickr con sus propias licencias individuales). Conviene confirmarlo antes de un uso público amplio.
/dashboard)Pagina con estadisticas agregadas (personas, respuestas, hubs y paises,
edades, imagenes mas confundidas, filtro por hub). Para activarla, ejecuta
una vez supabase/dashboard.sql en el SQL Editor de Supabase: crea la
funcion dashboard_stats(), que devuelve solo agregados a la anon key, asi
que no hace falta anadir la service_role key a Vercel.