# Juegoland Primera versión de una plataforma de juegos online en español. Svelte 5 + SvelteKit 3, Node.js, Socket.IO y PostgreSQL. Despliegue nativo con systemd detrás del proxy HTTPS de la red. ## Qué funciona - Registro con correo, nombre y nick; PIN de cuatro cifras protegido con scrypt y secreto del servidor; sesiones opacas en cookies HttpOnly. - Catálogo, búsqueda y filtros; salas públicas y privadas por invitación; estado «listo». - Ajedrez, damas de recorrido largo, parchís, Go 9×9 y la oca, con las variantes descritas en la ayuda. - Validación de reglas, dados y resultados en el servidor; acciones idempotentes y control de versión. - Chat de sala, consulta de reglas, registro de jugadas y reconexión al estado persistido. - Perfil e historial con victoria, derrota, empate y posición. - Interfaz adaptada a móvil, temas claro/oscuro, avatar, color de fichas, sonidos y animaciones de cada juego. - Salida de partidas y cierres sin resultado por inactividad; pendientes actualizadas en tiempo real. - Servicio personal en desarrollo de Juan V. Navarro Leal: popup breve de entrada visible desde el HTML del servidor y aceptación recordada con una cookie firmada. Sus botones permiten aceptar o salir también antes de inicializar JavaScript. Al rechazar el aviso, se vuelve a imaginacion.com. ## Desarrollo local Requiere Node.js 24 o superior. No necesita una base de datos para la primera prueba. ```sh npm ci npm run dev ``` Abre `http://localhost:4173`. Este puerto evita un conflicto local detectado con 5173. Vite encamina `/api` y `/socket.io` al servidor Node en `127.0.0.1:3001`. En desarrollo sin `DATABASE_URL`, las cuentas y partidas se guardan en `.data/development.json`. Es un almacén local de **un solo proceso**, para desarrollo; no debe usarse en producción ni como almacenamiento compartido. Está excluido de Git. La aplicación se niega a arrancar en producción sin PostgreSQL. Para jugar, abre dos navegadores o perfiles separados, entra con dos identidades invitadas o cuentas, acepta el aviso de entrada y entra en la misma sala mediante su código. Todos los jugadores deben marcar «Estoy listo». Los nombres de duración del catálogo son estimaciones, no límites de tiempo. ## PostgreSQL Configura `.env` a partir de `.env.example` y añade `DATABASE_URL` apuntando a una base dedicada. Después: ```sh npm run db:migrate npm run dev ``` Las migraciones se ejecutan en una transacción y con bloqueo para evitar dos migraciones simultáneas. Las mutaciones de partidas utilizan `SELECT ... FOR UPDATE`; el estado, los eventos y los resultados se confirman juntos. Los datos del almacén local no se importan automáticamente a PostgreSQL. La estructura relacional incluye usuarios, sesiones, salas/partidas, eventos, mensajes y resultados. El estado específico de cada juego y la instantánea recuperable de la sala se guardan en JSONB. Las estadísticas se calculan a partir de partidas terminadas. ## Verificación ```sh npm run check npm run design:check npm test npm run build ``` Las pruebas cubren reglas, capturas encadenadas, promoción en damas, finales, azar, barreras, privacidad de salas, concurrencia, acciones repetidas, recuperación del almacenamiento y el flujo real HTTP/WebSocket entre dos clientes. Estas pruebas usan el almacén local. La conexión, persistencia tras reinicio y restauración de PostgreSQL se han comprobado en la VM. ## Arquitectura y nuevos juegos - `src/routes`: catálogo, cuenta, perfil, ayuda y sala. - `src/lib/components`: ilustraciones y componentes de interfaz. - `shared/catalog.mjs`: definiciones y reglas visibles para el usuario. - `server/games`: módulos de reglas, independientes de Svelte y del transporte. - `server/platform.mjs`: participantes, salas, acciones, chat y resultados. - `server/store.mjs`: implementaciones local y PostgreSQL. - `server/service.mjs`: API, sesiones, origen, límites y WebSockets. - `db`: migraciones versionadas. - `deploy`: configuración nativa para Debian. El contrato de un juego es `id`, `version`, `minPlayers`, `maxPlayers`, `create`, `legal`, `apply` y `view`. `apply` devuelve `{ state, label, result }`; `result` contiene ganador y motivo o es `null`. Para añadir un juego, registra un módulo de confianza en `registry.mjs`, añade su manifiesto al catálogo y su componente de tablero. No se ejecuta código subido por usuarios. Un juego con información oculta debe filtrar su estado en `view` antes de enviarlo. Las partidas guardan la versión de reglas y fallan explícitamente si deja de estar disponible. Se ha elegido un contrato pequeño de reglas con Socket.IO para esta primera versión: evita adaptar cuentas, resultados y variantes al modelo de un motor externo. boardgame.io y Colyseus quedan como alternativas a evaluar si aparecen fases simultáneas, bots o necesidades de escalado. Un único servidor de partidas es la topología inicial; antes de levantar varias instancias habrá que coordinar presencia y publicaciones entre ellas. ## Límites de esta primera versión Modalidades casuales, sin reloj, ranking, torneos, bots, espectadores ni penalización por desconexión. Ajedrez declara automáticamente tablas por triple repetición y 50 movimientos. Damas permite damas de recorrido largo, captura obligatoria y saltos encadenados. Parchís utiliza una variante básica explícita, no todas las reglas de competición. El chat de consulta es la ayuda de reglas; no hay asistente de IA ni servicio de soporte conectado. Antes de abrir registro público quedan verificación y recuperación por correo (requieren proveedor SMTP), moderación/bloqueo/reportes, gestión de cuentas y políticas de conservación de datos. La versión está instalada en la VM con PostgreSQL y systemd. El acceso público requiere conectar DNS y el proxy HTTPS a juegoland.imaginacion.com; consulta deploy/server-status.md. La guía de instalación está en [deploy/README.md](deploy/README.md). La dirección visual y el prompt para otra herramienta están en [docs/design.md](docs/design.md). Los tokens, sus roles y la política de estilos están en [docs/design-system.md](docs/design-system.md). La auditoría `design:check` detecta valores de tipografía, espaciado y radios escritos a mano y variables CSS sin definir; también se ejecuta antes de activar un despliegue.