TicTacToe

Tres en Raya Online

Juego de Tres en Raya (TicTacToe) multijugador online con cuentas de usuario, emparejamiento por nivel, ranking ELO, progresión (XP/niveles) y logros.

Todo vive en un monorepo y se despliega como un único servicio (API HTTP + WebSocket + cliente web estático, servidos por el mismo proceso Node).

Características

Estructura del monorepo

.
├── package.json            # Workspaces npm + scripts
├── packages/
│   └── shared/             # @ttt/shared: tablero, ELO, XP/niveles, logros (+ tests)
└── apps/
    ├── server/             # @ttt/server: Express + Socket.IO + SQLite + auth
    └── web/                # @ttt/web: cliente web estático (SPA)

Requisitos

Desarrollo

npm install        # instala todas las dependencias del monorepo
npm run dev        # arranca el servicio único en http://localhost:3000 (con --watch)

Abre http://localhost:3000, regístrate y pulsa Buscar partida. Para probar el multijugador en local, abre una segunda sesión (ventana de incógnito u otro navegador) y regístrate con otra cuenta.

Scripts

Comando Descripción
npm run dev Servidor en modo desarrollo (recarga con --watch)
npm start Servidor en modo producción
npm test Tests unitarios de la lógica compartida

Variables de entorno

Copia .env.example a .env. Las más importantes:

Despliegue (un único servicio)

La app necesita un proceso Node persistente porque usa WebSockets (Socket.IO) y mantiene el emparejamiento/las salas en memoria, además de SQLite en disco.

Despliegue GRATIS (recomendado): Render + Postgres

La forma más rápida y gratis (una sola instancia, sin tarjeta) es Render (web service) con Postgres como base de datos persistente. El repo ya trae Dockerfile y render.yaml.

Pasos:

  1. Sube el repo a GitHub.
  2. En Render: New → Blueprint y selecciona tu repo. El render.yaml crea el web service (Docker) + un Postgres, y autogenera JWT_SECRET.
  3. Espera al deploy y abre la URL *.onrender.com. ¡Listo!

Detalles del plan gratis (importantes):

Comparativa rápida de opciones gratis (2026):

Componente Gratis recomendado Notas
App (Node + WebSocket) Render web service free Se duerme a los 15 min; WebSockets OK
Base de datos Neon (o Render Postgres) Neon: permanente; Render: caduca a 30 días
Redis (solo si escalas) Upstash free No hace falta con una sola instancia

Nota: Fly.io ya no tiene plan gratuito permanente (solo $5 de crédito de prueba). Railway tampoco es gratis a largo plazo. Otras opciones de pago sencillas: Railway, Fly.io, Google Cloud Run o un VPS.

# Local con Docker (igual que en producción):
docker build -t tres-en-raya .
docker run -p 3000:3000 -e JWT_SECRET=$(openssl rand -hex 32) -v ttt-data:/app/data tres-en-raya

Nota sobre Vercel

Vercel es serverless: sus funciones son efímeras y sin estado, por lo que no pueden mantener conexiones WebSocket persistentes ni el estado del matchmaking en memoria, y su sistema de archivos no persiste SQLite. Por eso el servidor de juego no funciona en las funciones serverless de Vercel tal cual. Para conservar “un mismo servicio” usa un host con proceso Node persistente (Render/Railway/Fly/Cloud Run) como se indica arriba. Si en el futuro se quisiera usar Vercel, habría que migrar el tiempo real a un servicio externo (p. ej. Ably/Pusher) y SQLite a una base de datos gestionada.

Escalabilidad (horizontal)

Por defecto la app corre como una sola instancia (SQLite + estado en memoria), ideal para desarrollo. Para escalar horizontalmente a varias instancias detrás de un balanceador, define dos variables de entorno y el código cambia de modo automáticamente (sin tocar la lógica):

# Ejemplo local con dos instancias compartiendo Postgres + Redis:
DATABASE_URL=postgres://ttt:ttt@localhost:5432/ttt REDIS_URL=redis://localhost:6379 \
  JWT_SECRET=xxxx INSTANCE_ID=app1 PORT=3001 npm start
DATABASE_URL=postgres://ttt:ttt@localhost:5432/ttt REDIS_URL=redis://localhost:6379 \
  JWT_SECRET=xxxx INSTANCE_ID=app2 PORT=3002 npm start

Topología escalable con Docker Compose

El repo incluye docker-compose.yml y deploy/nginx.conf con una topología de referencia: 2 réplicas de la app + Postgres + Redis + nginx (balanceador con afinidad de sesión ip_hash y soporte WebSocket).

docker compose up --build   # app en http://localhost:8080

Notas de escalado:

Seguridad