Proyectos
2026 Proyecto personal Live

World Cup Live 2026

Tablero del Mundial en tiempo real: marcadores en vivo, fixture por fecha, bracket y tablas de grupos, con datos de la API pública de ESPN.

Rol
Proyecto personal
Duración
2026
Año
2026
Estado
Live
TypeScript strict Cloudflare Workers Durable Objects WebSockets Web Push / Service Workers Vite Tailwind CSS
Tablero del Mundial 2026 con marcadores en vivo

El contexto

Quería seguir el Mundial 2026 en un tablero propio: marcadores en vivo, fixture por fecha, bracket y tablas de grupos, alimentado por la API pública de ESPN. El reto interesante no era la UI, sino sostener estado en tiempo real de forma barata y confiable en el edge, sin un servidor tradicional siempre encendido.

Decisiones técnicas

1. Estado en tiempo real con Durable Objects

El estado en vivo de los partidos vive en Durable Objects con SQLite: un punto de coordinación con estado sobre una plataforma serverless. Cada cliente se conecta al mismo objeto y recibe las actualizaciones sin que haya que sincronizar réplicas entre regiones.

2. WebSockets con hibernation, reconexión y fallback

Los marcadores se envían por WebSockets usando la API de hibernation de Cloudflare: el objeto puede dormir entre eventos sin cerrar las conexiones, así no se paga por mantenerlas abiertas mientras no hay goles.

// El objeto acepta el socket con hibernation en vez de un handler en memoria
export class MatchRoom {
  constructor(private state: DurableObjectState) {}

  async fetch(req: Request) {
    const [client, server] = Object.values(new WebSocketPair());
    this.state.acceptWebSocket(server); // sobrevive a la hibernación
    return new Response(null, { status: 101, webSocket: client });
  }

  // Se re-invoca al despertar; no hace falta estado en memoria
  webSocketMessage(ws: WebSocket, msg: string) {
    /* difusión del marcador a los clientes suscritos */
  }
}

En el cliente hay reconexión automática y un fallback a polling cuando el socket no está disponible, para que el marcador nunca se quede congelado.

3. Notificaciones Web Push a bajo nivel

Las notificaciones (“¡Gol!”, inicio de partido) usan Web Push implementado a mano: VAPID y el cifrado de payload de la RFC 8291 con Web Crypto (ECDH para el acuerdo de claves y AES-GCM para el contenido), disparadas desde un service worker. Hacerlo sin librería obligó a entender el protocolo real de push en vez de tratarlo como una caja negra.

Lo que aprendí

  • Los Durable Objects hacen que “serverless con estado” deje de ser un oxímoron: la coordinación en vivo cabe en el edge sin infraestructura dedicada.
  • La hibernation cambia el modelo mental de los WebSockets: el estado no vive en memoria del proceso, vive en el objeto.
  • Implementar Web Push desde el RFC enseña más que cualquier SDK: entender ECDH y AES-GCM aplicados a un caso concreto quita el miedo a la criptografía.

Más capturas

Bracket de eliminatorias
Bracket de eliminatorias
Tabla de grupos
Tabla de grupos