Add planning docs, design system, and Stitch mockups
- CLAUDE.md: project guidance (stack, domain model, auth, i18n, gotchas) - DESIGN.md: full design system spec derived from Stitch mockups (slate monochrome, Inter, shadcn-svelte, screen patterns for all 5 views) - README.md: development plan with Justfile commands - analysis/: functional spec (domain model, use cases, business rules) - plan/: phase-by-phase implementation plans (Fase 0–4) - .stitch/designs/: generated mockups (lists, shopping session, notes, tasks, list detail with frequency chips) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
192
README.md
Normal file
192
README.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Plan de Desarrollo — App Gestión del Colectivo
|
||||
> **Stack:** SvelteKit + Supabase self-hosted + PWA
|
||||
> **Infraestructura:** Docker Compose (dev local + producción VPS)
|
||||
> **Última actualización:** Abril 2026
|
||||
|
||||
---
|
||||
|
||||
## Índice de Fases
|
||||
|
||||
| Fase | Archivo | Duración estimada |
|
||||
|------|---------|-------------------|
|
||||
| Fase 0 | [fase-0-infraestructura.md](fase-0-infraestructura.md) | 1–2 semanas |
|
||||
| Fase 1 | [fase-1-auth-colectivo.md](fase-1-auth-colectivo.md) | 2–3 semanas |
|
||||
| Fase 2a | [fase-2a-lista-compra-crud.md](fase-2a-lista-compra-crud.md) | 2 semanas |
|
||||
| Fase 2b | [fase-2b-realtime-modo-compra.md](fase-2b-realtime-modo-compra.md) | 2–3 semanas |
|
||||
| Fase 3 | [fase-3-tareas-notas.md](fase-3-tareas-notas.md) | 1–2 semanas |
|
||||
| Fase 4 | [fase-4-busqueda-pulido.md](fase-4-busqueda-pulido.md) | 1 semana |
|
||||
|
||||
**Total estimado: 9–13 semanas**
|
||||
|
||||
---
|
||||
|
||||
## Stack Tecnológico Confirmado
|
||||
|
||||
| Capa | Tecnología | Justificación |
|
||||
|------|-----------|---------------|
|
||||
| Frontend / PWA | SvelteKit 2 | Reactividad nativa, bundle pequeño, PWA de primera clase |
|
||||
| Backend / BaaS | Supabase self-hosted | Realtime, RLS, Storage — Auth delegada a Keycloak |
|
||||
| Identidad / Auth | Keycloak self-hosted | IdP OIDC/OAuth2, gestión de usuarios, federación futura |
|
||||
| Base de datos | PostgreSQL 15 (vía Supabase) | Full-text search nativo, `pg_cron` para jobs |
|
||||
| Tiempo real | Supabase Realtime (WebSocket) | Presencia + cambios en < 1s sin infraestructura extra |
|
||||
| Offline | IndexedDB vía `idb` | PWA-compatible, sin dependencias nativas |
|
||||
| PWA | `@vite-pwa/sveltekit` + Workbox | Service Worker, caché offline, instalable |
|
||||
| Infraestructura dev | Docker Compose + Supabase CLI | Entorno local con Studio + Keycloak + usuarios de prueba |
|
||||
| Infraestructura prod | Docker Compose + nginx (existente) | Reverse proxy ya operativo en el VPS, gestionado externamente |
|
||||
| CI/CD | GitHub Actions | Lint, test, deploy vía SSH |
|
||||
| Email transaccional | Resend | SMTP para invitaciones (Keycloak también lo usa para reset) |
|
||||
| Backups | `pg_dump` → Backblaze B2 (S3) | Retención 30 días, coste mínimo |
|
||||
|
||||
---
|
||||
|
||||
## Estructura del Repositorio
|
||||
|
||||
```
|
||||
colectivo/
|
||||
├── apps/
|
||||
│ └── web/ # SvelteKit — web + PWA
|
||||
│ ├── src/
|
||||
│ │ ├── lib/
|
||||
│ │ │ ├── supabase.ts # cliente Supabase singleton
|
||||
│ │ │ ├── auth.ts # cliente OIDC (keycloak-js) + helpers de sesión
|
||||
│ │ │ ├── stores/ # Svelte stores globales
|
||||
│ │ │ ├── sync/ # lógica offline + cola de operaciones
|
||||
│ │ │ └── components/ # componentes UI reutilizables
|
||||
│ │ ├── routes/ # rutas SvelteKit
|
||||
│ │ └── service-worker.ts # SW personalizado (Workbox)
|
||||
│ ├── static/
|
||||
│ │ ├── manifest.webmanifest
|
||||
│ │ └── icons/ # iconos PWA (512, 192, 180...)
|
||||
│ └── vite.config.ts
|
||||
│
|
||||
├── packages/
|
||||
│ └── types/ # tipos TypeScript compartidos
|
||||
│ └── src/
|
||||
│ ├── database.ts # tipos generados desde schema Supabase
|
||||
│ └── domain.ts # tipos de dominio (Colectivo, Item, etc.)
|
||||
│
|
||||
├── supabase/
|
||||
│ ├── migrations/ # migraciones SQL versionadas
|
||||
│ ├── seed.sql # datos de prueba para dev
|
||||
│ ├── functions/ # Edge Functions (invitaciones, etc.)
|
||||
│ └── config.toml # configuración Supabase CLI + OIDC Keycloak
|
||||
│
|
||||
├── keycloak/
|
||||
│ ├── realm-export.json # realm "colectivo" exportado — importado al arrancar dev
|
||||
│ └── themes/ # tema personalizado (opcional, v2)
|
||||
│
|
||||
├── infra/
|
||||
│ ├── docker-compose.dev.yml # Supabase + Keycloak + SvelteKit dev
|
||||
│ ├── docker-compose.prod.yml # producción en VPS
|
||||
│ └── scripts/
|
||||
│ ├── backup.sh # backup manual de una BD concreta
|
||||
│ ├── backup-cron.sh # ejecutado por cron: decide tipo (diario/semanal/mensual) y purga
|
||||
│ ├── restore.sh # restaura un dump concreto en una BD
|
||||
│ └── deploy.sh # SSH + docker compose pull + up
|
||||
│
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ ├── ci.yml # lint + test en PR
|
||||
│ └── deploy.yml # deploy en push a main
|
||||
│
|
||||
├── .env.example # todas las variables documentadas con valores de ejemplo
|
||||
├── Justfile # comandos de desarrollo frecuentes
|
||||
├── turbo.json # Turborepo pipeline
|
||||
└── package.json # workspaces
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Justfile — Comandos de referencia
|
||||
|
||||
```bash
|
||||
just dev # levanta docker-compose.dev.yml + SvelteKit dev server
|
||||
just dev-stop # para el entorno local
|
||||
just db-reset # drop + migrate + seed (dev)
|
||||
just db-migrate # aplica migraciones pendientes (dev)
|
||||
just db-types # genera tipos TS desde schema Supabase → packages/types
|
||||
just kc-export # exporta realm de Keycloak → keycloak/realm-export.json
|
||||
just kc-open # abre Keycloak Admin Console en el navegador (localhost:8080)
|
||||
just deploy # ejecuta infra/scripts/deploy.sh (prod)
|
||||
just backup supabase # backup manual inmediato de supabase
|
||||
just backup keycloak # backup manual inmediato de keycloak
|
||||
just restore supabase <file> # restaura un dump concreto en supabase
|
||||
just restore keycloak <file> # restaura un dump concreto en keycloak
|
||||
just logs # docker compose logs -f (prod)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Decisiones Previas al Inicio
|
||||
|
||||
Antes de arrancar la Fase 0, confirmar:
|
||||
|
||||
| Decisión | Estado |
|
||||
|----------|--------|
|
||||
| Estrategia JWT Keycloak → Supabase (Opción A vs B) | Pendiente — **Opción A recomendada** |
|
||||
| Base de datos de Keycloak en prod | ✅ **PostgreSQL independiente** |
|
||||
| Entorno de producción dockerizado | ✅ **Ya operativo** |
|
||||
| Reverse proxy en producción | ✅ **nginx existente, gestionado externamente** |
|
||||
| Self-registration habilitado en Keycloak o invitación obligatoria | Pendiente |
|
||||
| Proveedor SMTP para Keycloak y Resend (emails de invitación) | Pendiente — **Resend recomendado** |
|
||||
| Almacenamiento de backups | Pendiente — **Backblaze B2 recomendado** |
|
||||
| Dominio y DNS del VPS | Pendiente |
|
||||
| Subdominio para Keycloak | Pendiente — `auth.tudominio.com` recomendado |
|
||||
| Registry de imágenes Docker | Pendiente — **GitHub Container Registry recomendado** |
|
||||
| OAuth Google (federated en Keycloak) | Pendiente — configurar en Keycloak, no en Supabase |
|
||||
| OAuth Apple (federated en Keycloak) | Pendiente — requiere Apple Developer Program ($99/año) |
|
||||
|
||||
---
|
||||
|
||||
## Advertencias Técnicas
|
||||
|
||||
**Keycloak y JWT con Supabase RLS:**
|
||||
- Supabase RLS usa `auth.uid()` que lee el claim `sub` del JWT. Verificar que el `sub` de Keycloak es un UUID v4 estándar — por defecto lo es, pero algunos realms lo configuran diferente.
|
||||
- En la Opción A (JWT directo), la clave pública de Keycloak (RS256) debe estar en `JWT_SECRET` de Supabase. Si rotas las claves de firma en Keycloak, debes actualizar Supabase también.
|
||||
- Keycloak tiene sesiones propias independientes de Supabase. Un `logout()` debe invalidar en ambos lados: llamar a `keycloak.logout()` (que invalida en Keycloak) y limpiar el cliente de Supabase localmente.
|
||||
|
||||
**Keycloak self-hosted en producción:**
|
||||
- Keycloak 24+ requiere mínimo 512MB de RAM asignados. En un VPS pequeño (2GB), monitorizar el consumo conjunto con Supabase.
|
||||
- El endpoint `/realms/{realm}/.well-known/openid-configuration` debe ser accesible públicamente para que Supabase pueda validar tokens. No poner Keycloak detrás de autenticación básica.
|
||||
- Habilitar `SSL Required: external requests` en el realm de producción. Nunca desactivarlo.
|
||||
|
||||
**OAuth federado (Google, Apple):**
|
||||
- Con Keycloak, Google y Apple se configuran como Identity Providers en Keycloak, no en Supabase. El flujo es: usuario → Keycloak → Google/Apple → Keycloak → app. Supabase solo ve el token de Keycloak.
|
||||
- Esto simplifica la configuración de Supabase pero requiere configurar los Identity Providers en Keycloak Admin Console.
|
||||
|
||||
**iOS Safari y PWA:**
|
||||
- Background Sync API no está soportada en Safari. Implementar fallback manual con el evento `online`.
|
||||
- Push notifications solo disponibles desde iOS 16.4 y únicamente con la PWA instalada en pantalla de inicio.
|
||||
- `keycloak-js` usa iframes para el refresco silencioso del token (`checkLoginIframe`). Deshabilitarlo en la config (`checkLoginIframe: false`) porque Safari bloquea cookies de terceros en iframes — usar `updateToken()` manual en su lugar.
|
||||
- Probar el Modo Compra en un iPhone real en paralelo al desarrollo, no solo en DevTools.
|
||||
|
||||
**Supabase Realtime self-hosted:**
|
||||
- Revisar `MAX_REPLICATION_SLOTS` en PostgreSQL y `REALTIME_MAX_CONNECTIONS` antes de producción.
|
||||
- Las suscripciones de Presence consumen más recursos que Postgres Changes. Limitar a listas con sesión activa.
|
||||
|
||||
**Conflictos de sincronización:**
|
||||
- Last-write-wins es suficiente para este dominio. No implementar CRDT en el MVP.
|
||||
- Registrar conflictos detectados en tabla `sync_conflicts` para depuración.
|
||||
|
||||
---
|
||||
|
||||
## Estimación Total
|
||||
|
||||
| Fase | Duración |
|
||||
|------|----------|
|
||||
| Fase 0 — Infraestructura | 1–2 semanas |
|
||||
| Fase 1 — Auth y Colectivo | 2–3 semanas |
|
||||
| Fase 2a — Lista de Compra CRUD | 2 semanas |
|
||||
| Fase 2b — Realtime y Modo Compra | 2–3 semanas |
|
||||
| Fase 3 — Tareas y Notas | 1–2 semanas |
|
||||
| Fase 4 — Búsqueda y Pulido | 1 semana |
|
||||
| **Total** | **9–13 semanas** |
|
||||
|
||||
---
|
||||
|
||||
*Plan generado como base para Claude Code. Stack: SvelteKit + Supabase self-hosted + Keycloak + PWA. Cada fase puede usarse como contexto independiente para sesiones de trabajo.*
|
||||
|
||||
Reference in New Issue
Block a user