Base modular reutilizable para apps web AR/multimedia educativas. Este repositorio contiene
el código de la WMB. La documentación de método (el "por qué") y los logs de cada fase viven
en el workspace del proyecto (carpetas 01 - Docs base metodo y 04 - Recomendaciones al sistema),
fuera de este repositorio.
Estado: Fases 4–9 + grafo de escenas hechas. Vite + 21 módulos + core + ui + 3 paneles de admin. 90/90 tests, build verde. i18n (ES/EN runtime), PWA offline, captura/compartir, galerías (video/audio/3D/360), lector PDF, capa "skin", y navegación por grafo editable.
La WMB no identifica ningún proyecto final. Hay dos capas:
- Núcleo reutilizable —
src/core/,src/ui/,src/modules/,styles/,identity.js. No contiene nada de un proyecto concreto. - Capa de proyecto (removible) —
public/data/,public/qiri.config.json,public/data/identity.json,public/data/scenes.json,assets/,public/vendor/. Aquí vive todo lo que cambia entre apps. Los placeholders actuales son una demo "todo Qiri" removible (marca, textos, escena demo).
Nuevo proyecto = copiar este repositorio y reemplazar la capa de proyecto (config + data +
identidad + scenes + assets). No se toca el núcleo para meter contenido. (Flujo detallado en la
doc de método del workspace: 01 - Docs base metodo/05 - Flujo de Trabajo por Proyecto.)
02 - Qiri WMB/
├── package.json · vite.config.js · vitest.config.js ← 4 entradas: app + 3 admins
├── index.html ← entry app: <script src="/src/main.js">
├── identity.js ← identidad → CSS vars (dual: ES export + window). Incluye capa skin.
├── public/
│ ├── qiri.config.json ← manifiesto del proyecto (idiomas, módulos, ar, memoria)
│ ├── data/ ← contenido por proyecto (JSON)
│ │ ├── i18n/{es,en}.json ← textos de UI por idioma (placeholders → t("clave"))
│ │ ├── identity.json ← marca/colores/tipografía/botones/skin
│ │ ├── scenes.json ← MAPA DE NAVEGACIÓN por grafo (scenes/nodes/edges)
│ │ ├── menu.json · *.json ← datos de cada pantalla (galerías, biblioteca, etc.)
│ ├── vendor/ ← three + mind-ar + pdf.js self-hospedados (OFFLINE)
│ ├── pdf/placeholder.pdf ← PDF de prueba para el lector
│ ├── sw.js · manifest.webmanifest · icon.svg ← PWA (offline-first)
│ └── spike.html · spike-assets/ ← spike AR desechable (validado)
├── src/
│ ├── main.js · app.js ← estilos + boot (servicios, módulos, Router, grafo)
│ ├── core/ ← Router · Memory/Module/Overlay/Theme managers · AssetLoader ·
│ │ Storage · I18n · EventBus · Audio · Share · Capture ·
│ │ SceneGraph · Navigator · nav-helper(advance/dataFor)
│ ├── ar/ ← itracker + adapters (MindAR) · viewer3d · scene360
│ ├── ui/ ← h() + átomos (Button/Screen/List/Card/Carousel/Modal…)
│ ├── modules/ ← 21 pantallas (contrato load/mount/unmount/dispose)
│ └── __tests__/ ← Vitest (90): core, ui, módulos, servicios, grafo, editores
├── styles/ ← fonts · theme(tokens) · base · buttons · skin · transitions
├── identity-admin/ ← panel de IDENTIDAD (tema/colores/skin)
├── content-admin/ ← panel de CONTENIDOS (editor i18n: claves×idioma)
├── scene-admin/ ← editor de ESCENAS (mapa de navegación visual, node-graph)
└── assets/ ← fonts (Open Sans), logos
Cada módulo es una carpeta en src/modules/<id>/ que exporta un objeto:
export default {
id: "mi-modulo",
heavy: false, // true = WebGL/cámara → 1 activo a la vez (MemoryManager)
load?(ctx) { /* async opcional → ctx.loaded */ },
mount(ctx) { /* devuelve el nodo DOM de la pantalla */ },
unmount?(ctx) {}, dispose?(ctx) { /* libera listeners/WebGL */ },
};ctx = { router, params, data, services }. Reglas: textos por t("clave")
(ctx.services.i18n), datos por ctx.data.<clave> (o dataFor(ctx, "clave") para permitir
override por nodo del grafo), átomos desde ui/, navegación por advance(ctx, intención, fallback).
Documentación técnica por aspecto: índice · arquitectura · contrato de módulo · UI/estilos/responsive · i18n · PWA/offline · captura/compartir · galerías/visores · skin · grafo de escenas · paneles admin · bifurcar a un proyecto.
- i18n (ES/EN) —
data/i18n/<lang>.json; cambio en runtime desde Opciones; idioma guardado. - PWA offline —
sw.jscache-first para/vendor/, precache de shell+data+i18n. Instalable. - Captura & compartir —
ShareService(Web Share + fallbacks),CaptureService(foto compuesta cámara+3D, video MediaRecorder),camerareal +device-gallery. - Galerías data-driven —
gallery-video/audio/3d/360+librarycon lector PDF (pdf.js). - 3D / 360 —
ar/viewer3d(modelos .glb, orbit) yar/scene360(esfera equirectangular, look-around); three self-hospedado, carga diferida,dispose()libera WebGL. - Skin (estilo videojuego) — tokens
--skin-*+data-skin+styles/skin.css(9-slice, bisel, texturas). Default plano (sin cambios). Se activa rellenandoidentity.json → skin. - Grafo de escenas — la navegación NO está hardcodeada: vive en
data/scenes.json(escenas reutilizables → nodos → transiciones). ElNavigatorlo ejecuta con fallback alrouter.gode siempre. Editable visualmente enscene-admin/. Una misma escena puede usarse en varios nodos (reuso), con datos distintos por nodo.
cd "02 - Qiri WMB"
npm install
npm run dev # http://localhost:5173 (HTTP)
npm run dev:https # HTTPS (cámara AR / captura)
npm run build # genera dist/ (app + 3 admins)
npm run preview # sirve el build (aquí SÍ se registra el Service Worker)
npm test # Vitest (90 tests)Probar en el teléfono: misma WiFi → la URL Network de Vite (http://<IP-del-PC>:5173).
/identity-admin/— tema, colores, tipografía, botones y skin; exportaidentity.json./content-admin/— editor de textos i18n (tabla clave×idioma, faltantes); exporta<lang>.json./scene-admin/— editor visual del mapa de navegación (nodos = escenas, aristas = transiciones); validación en vivo; importa/exportascenes.json.
Los admins son estáticos (sin backend): exportan archivos que reemplazas en
public/data/.
El motor vive tras src/ar/itracker.js (intercambiable MindAR↔8th Wall); el adapter carga
three+mind-ar self-hospedados en public/vendor/ (offline) y de forma diferida (al pulsar
"Iniciar AR"). El import-map de index.html apunta a /vendor/three. Probar en dispositivo:
npm run dev + túnel (cloudflared) → Iniciar Experiencia → loader → Iniciar AR → marcador.
Configurar en public/qiri.config.json → ar: targetSrc (.mind), targetImg, modelSrc (.glb;
vacío = torus de prueba).
- Pasos 0–3 — Vite/HTTPS · spike AR validado (iPhone 60 FPS) · pantallas congeladas ·
refactor modular (
core/modules/ui). - Fase 4 — i18n multi-idioma (ES/EN runtime) · PWA offline robusto · manejo de errores.
- Fase 5 — captura & compartir (foto/video + Web Share + galería del dispositivo).
- Fase 6 — galerías video/audio/3D + lector PDF (pdf.js).
- Fase 7 — sistema 360 (visor Scene360) + grafo de escenas (runtime + editor visual).
- Fase 8 — infraestructura de skin (tokens; arte real = capa de proyecto).
- Fase 9 — editores de admin: contenidos (i18n) y escenas (grafo).
- Contenido real (videos/audios/.glb/PDF/panoramas 360), dirección de arte del skin.
- Experiencia AR graph-driven (hoy usa loader especial) — decisión de UX.
- Iconos PWA en PNG (iOS), prueba de AR/cámara en dispositivo real.