01-overview.md
Visión general · GameVault
GameVault (repo videogames-library) es una Progressive Web App Angular/Ionic para mantener una biblioteca personal de videojuegos: alta y edición de títulos, filtros densos, playtime, wishlist, historial de partidas e insights. La nube es Neon Auth + Data API (Postgres). Deploy en Netlify.
No es un monorepo Nest: un solo paquete Angular, equivalente a Presencia. El “command center” (sidebar, ⌘K, colecciones smart) es el producto, no un CRUD genérico.
Enlaces
- Web: https://videogames-library.netlify.app
- GitHub: Criscode2022/videogames-library
- Producto:
package.jsonnamevideogames-library· marca GameVault
Stack
| Capa | Tecnología |
|---|---|
| Web | Angular 19, Ionic 8, Tailwind 4, standalone components |
| Auth | Neon Auth (email/password, cookie + JWT fallback iOS) |
| Datos | Neon Data API (PostgREST) vía DatabaseService |
| Extra | RAWG API (búsqueda de portadas + recomendaciones, sin IA) |
| Deploy | Netlify (dist/videogames-library/browser + SPA rewrite) |
02-product.md
Producto y features
Problema
Las colecciones se fragmentan entre Excel, notas, Steam y la cabeza. Falta un vault de confianza para plataforma, horas, estado y wishlist cuando el backlog no cabe en un solo store.
Solución
Command center de biblioteca: colecciones smart, paleta ⌘K, tres vistas (grid / lista / estantería), Continue Playing, tags, wishlist con countdown, log de sesiones e insights. Auth Neon; persistencia en Postgres.
Características
Biblioteca
Filtros por plataforma, año, desarrollador, rating, última partida y playtime. Tags y colecciones guardadas. Import JSON; export JSON y Excel.
Vistas
Grid (cartas con cover 3:4), lista densa y shelf. La preferencia se persiste.
Wishlist
Títulos próximos con cuenta atrás de lanzamiento. “Add to library” cuando ya salió.
Playtime e historial
Log rápido de horas en la ficha; timeline de partidas completadas.
Insights y For you
Racha, % completado, horas por plataforma/género. Recomendaciones RAWG a partir del gusto de la librería (sin modelo de IA).
Paleta ⌘K
Salto a juegos, colecciones y acciones (Ctrl/⌘K).
03-architecture.md
Arquitectura
Diagrama lógico
Browser / PWA Ionic (Angular 19)
│ sesión: Neon Auth cookie + JWT fallback
│ datos: HTTP Data API (PostgREST)
▼
Neon Auth (email / password)
Neon Data API ──► Postgres (schema public)
RAWG API (opcional) ──► portadas + recomendaciones
Capas
- Shell —
AppShellComponent: sidebar de colecciones, search ⌘K, tabs móviles. - Páginas —
home,game/:id,add/edit/:id,wishlist/add,play-history,insights,recommendations,profile. - Servicios —
GameService,AuthService,DatabaseService,RawgService,RecommendationsService, prefs de vista. - Guards —
AuthGuarden el shell;loginGuarden/loginy/register.
Principios
- Un vault, un usuario: las filas llevan
user_id. - RAWG es enriquecimiento, no fuente de verdad.
- Sin Nest: el contrato cabe en Auth + Data API.
- Estética Refined Vault: neon ganado, no wallpaper.
04-monorepo.md
Estructura (app única)
GameVault no es un monorepo Turborepo: un solo paquete Angular/Ionic.
| Path | Rol |
|---|---|
src/app/layout/app-shell | Command center (sidebar + tabs) |
src/app/pages/home | Biblioteca + filtros + vistas |
src/app/pages/game-detail | Ficha, rating, log de horas |
src/app/pages/game-form | Alta / edición / wishlist |
src/app/pages/insights | Stats de la colección |
src/app/pages/recommendations | Picks RAWG |
src/app/pages/play-history | Timeline |
src/app/pages/login | Sign-in / register |
src/app/services | Games, auth, Data API, RAWG |
src/app/components/command-palette | ⌘K |
src/lib/auth.ts | Cliente Neon Auth (fetch + cookies) |
neon/ | Schema SQL + migrate/seed |
scripts/set-env.js | Genera environment.ts desde .env |
scripts/browser-check.mjs | Playwright smoke de rutas |
netlify.toml | Build + SPA fallback |
Scripts
| Script | Descripción |
|---|---|
npm start | set-env + ng serve |
npm run build | Producción → dist/videogames-library/browser |
npm run db:migrate / db:seed | Schema y seed en Neon |
node scripts/browser-check.mjs | Capturas e2e locales |
Package manager: npm. Node ≥ 18. Angular CLI 19.
05-api.md
Superficie API (Neon Auth + Data)
No hay Nest propio. El cliente habla con Neon Auth (src/lib/auth.ts) y con la Data API REST (DatabaseService + HttpClient).
Auth
sign-in/sign-upemailtoken(JWT desde cookie HttpOnly)get-session/sign-out- Fallback de sesión en
localStoragepara iOS cuando la cookie no es visible a JS
Data API (PostgREST)
DatabaseService construye queries select, filters (eq, ilike, in…), order, limit. Escrituras con Prefer: return=representation.
Tablas de producto (además del esquema seed inicial): games, plataformas, compañías, directores, sesiones de juego, tags. Las filas van filtradas por el usuario autenticado.
RAWG
RawgService rellena portadas y recomendaciones. Clave en .env (RAWG_API_KEY). Si falta, la biblioteca sigue funcionando con covers propias.
Por qué no hay /api Nest
El dominio es un único cliente: email, sesión y filas por usuario caben en Neon Auth + Data API. Task Cloud necesita Nest por PIN/JWT propio; aquí no.
06-auth.md
Modelo de autenticación
Flujo
- Registro o login email/password (
/register,/login). - Neon Auth (
authClient→ endpoints/token, sesión cookie). AuthGuardexige sesión para el shell;loginGuardsaca al usuario ya logueado de/login.AuthServiceguarda JWT (cookie o fallbackneon_auth_session_fallbacken iOS).- Logout:
signOut()+ limpieza de fallback.
Seguridad
- Contraseña y tokens los gestiona Neon Auth; el bundle no guarda secretos de servidor.
- El JWT se usa como Bearer en la Data API.
- 401 en Data API dispara un handling de sesión caducada (no bucle infinito).
Por qué email y no PIN
El vault tiene que recuperarse entre portátil y móvil. Neon Auth ya da email recuperable. Un PIN local (Task Cloud) no cubría “la misma biblioteca en dos dispositivos” sin un backend custom.
07-data-model.md
Modelo de datos
Entidades (game.model.ts)
Game
id, title, description, coverImage, platformId, developerId, directorId, releaseYear / releaseDate, genre[], tags[], rating, status (not_started | playing | paused | completed | wishlist), playtime, userId.
GamePlayStatus
Ciclo: not started → playing → paused → playing; completed y wishlist tienen transiciones propias. Completar limpia o conserva historial según reglas de game-status.utils.
PlaySession
gameId, userId, startedAt / endedAt, durationMinutes, notes.
Catálogos
Platform, Company (developer), Director — tablas auxiliares para filtros.
Neon
El schema seed (neon/schema.sql) arranca users, games, game_status. El cliente evoluciona el contrato (tags, sesiones, plataformas) con scripts db:migrate / db:add-tags y refresh del Data API schema.
Todas las lecturas de biblioteca van con user_id del JWT.
Local
Prefs de vista (grid/list/shelf) y fallback de sesión en localStorage. El catálogo no es offline-first: sin Data API no hay filas.
08-deploy-vercel.md
Deploy en Netlify
Idea
npm run build(prebuildset-envinyecta URLs de Neon y RAWG)- Publish
dist/videogames-library/browser - Catch-all SPA:
/*→/index.html200
Config (netlify.toml)
[build]
command = "npm run build"
publish = "dist/videogames-library/browser"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Las URLs de Neon Auth / Data API van en variables de entorno de Netlify (NEON_AUTH_URL, DATABASE_URL, RAWG_API_KEY). El cliente las lee desde environment.prod.ts generado en el build.
Smoke
- Abrir https://videogames-library.netlify.app
- Login → biblioteca con grid de covers
- Ficha de un título, ⌘K, wishlist, insights
Local
cp .env.example .env # Neon + RAWG
npm install
npm start # :4200 09-decisions.md
Decisiones
Neon Auth/Data en lugar de Nest propio
El contrato (email, sesión, filas por usuario) cabe en BaaS. Un Nest extra no aportaba PIN custom ni bulk jobs. Menos ops, un deploy estático.
Command center, no “CRUD de juegos”
Sidebar + ⌘K + smart collections son el ADN. Una lista con badges habría sido el anti-patrón de spreadsheet feo que el PRODUCT.md rechaza.
RAWG, no IA
Portadas y “For you” salen de un catálogo de videojuegos. Un LLM no añade verdad de metadatos y sí añade coste y alucinación.
Refined Vault
Cyberpunk contenido: Orbitron solo en marca; Inter en UI; glow en hover/foco. Rechaza RGB de feria y SaaS crema.
Netlify, no Vercel
SPA + rewrite encajan en netlify.toml sin función. Task Cloud necesita Vercel por Nest.
Angular 19 + Ionic 8 + Zone
Ionic 8 sigue pidiendo zone.js. No se fuerza zoneless ni Signal Forms de v21 (el techo de Task Cloud / Presencia).
10-challenges-results.md
Retos y aprendizajes
Cookie de sesión en iOS
Safari no expone cookies HttpOnly. AuthService lee JWT vía endpoint /token y guarda un fallback neon_auth_session_fallback para no perder la sesión al volver a la PWA.
Data API vs schema seed
El schema.sql inicial es mínimo (games + game_status). El cliente real usa plataformas, tags, sesiones y covers. Tras migrar hay que refrescar el schema de Data API (db:refresh-api-schema).
Densidad vs móvil
El command center de escritorio (sidebar + ⌘K) se traduce a tabs Ionic abajo y un drawer. La misma ficha de juego no puede ser un dashboard SaaS ni un grid vacío.
Resultados
- PWA en videogames-library.netlify.app.
- Biblioteca con covers, colecciones smart, wishlist, insights y paleta ⌘K.
- Auth Neon + Postgres Data API; RAWG opcional.
- Smoke Playwright (
scripts/browser-check.mjs) con capturas de home, alta, ficha, historial y móvil. - Código abierto como referencia Angular/Ionic + Neon + Netlify (hermano de Presencia; complemento de Task Cloud con Nest).
11-angular-skill.md
Angular en GameVault
App Angular 19 + Ionic 8 + TypeScript 5.6 + Zone. Componentes standalone, lazy loadComponent en app.routes.ts. Formularios con FormsModule / reactive (formControlName en login). No hay skill Angular versionada en el repo (a diferencia de Task Cloud).
Qué se aplica
| Práctica | Dónde |
|---|---|
| Standalone + lazy routes | Shell, home, ficha, form, insights |
| Signals + RxJS | GameService (signal + subjects) |
| Ionic tabs / drawer | Móvil vs sidebar desktop |
| HttpClient + PostgREST | DatabaseService |
| Guards funcionales y de clase | loginGuard, AuthGuard |
Techo Ionic 8
| API moderna | Por qué no se fuerza | Qué hay |
|---|---|---|
| Zoneless | Ionic 8 pide zone.js ~0.15 | Zone |
| Signal Forms v21+ | App en Angular 19 | Reactive / template forms |
| View Transitions del Router | Navegación Ionic | Transiciones Ionic |
| SSR | PWA + Auth cookie + Data API | SPA en Netlify |
Subir a Angular 21/22 exigiría alinear Ionic (mismo techo documentado en Task Cloud / Presencia).