Skip to content

On-Linces/aoc-leaderboard

Repository files navigation

AoC Leaderboard (Next.js)

Visualizador “pro” para leaderboards privados de Advent of Code: podium, tabla interactiva, detalle por miembro, modo Versus y una página de estadísticas.

Proyecto pensado para portafolio: mezcla frontend (UX + estado en cliente) con backend (API route + cache + variables de entorno) y performance (revalidación controlada).

Qué hace

  • Consume el JSON oficial del leaderboard privado de AoC.
  • Normaliza y ordena miembros por estrellas y score.
  • UI con:
    • Podium (top 3)
    • Tabla con modal de miembro
    • “Daily champion” (quién completó más rápido el último día activo)
    • Modo Versus (comparar 2 miembros)
    • Página /stats con KPIs + distribución por día y por hora

Cómo funciona (arquitectura)

Flujo de datos

  1. El cliente pide GET /api/aoc.
  2. El backend (Route Handler de Next) hace fetch al endpoint de AoC usando la cookie session.
  3. Para no spamear AoC y mantener la app rápida, la respuesta se cachea 15 minutos.
  4. La UI usa SWR para revalidar cada 15 min y al volver a enfocar la pestaña.

Piezas clave

  • app/api/aoc/route.ts: backend que obtiene + transforma + cachea el leaderboard.
  • app/page.tsx: UI principal (SWR, podium, tabla, detección de cambios con localStorage).
  • app/stats/page.tsx: estadísticas agregadas en cliente.

Fragmento de código (cache + fetch seguro)

Este handler encapsula el fetch a AoC y lo cachea con unstable_cache para reducir latencia y llamadas:

import { unstable_cache } from "next/cache";

const getCachedLeaderboard = unstable_cache(
	async () => {
		const res = await fetch(
			`https://adventofcode.com/${process.env.AOC_YEAR ?? "2024"}/leaderboard/private/view/${process.env.AOC_BOARD}.json`,
			{ headers: { Cookie: `session=${process.env.AOC_SESSION}` } }
		);

		if (!res.ok) {
			throw new Error(`Error AoC: ${res.status} ${await res.text()}`);
		}

		const data = await res.json();

		const members = Object.values(data.members || {}).map((m: any) => ({
			id: m.id,
			name: m.name,
			stars: m.stars,
			score: m.local_score,
			completion_day_level: m.completion_day_level,
		}));

		members.sort((a: any, b: any) => b.stars - a.stars || b.score - a.score);
		return { ok: true, updated: new Date().toISOString(), members };
	},
	["aoc-leaderboard-data"],
	{ revalidate: 900 }
);

Tecnologías

  • Next.js (App Router)
  • React + TypeScript
  • Tailwind CSS
  • SWR (cache/revalidate en cliente)

Requisitos

  • Node.js (recomendado 18+)
  • Una cookie de sesión válida de Advent of Code

Variables de entorno

Crea un archivo .env.local en la raíz:

AOC_SESSION=tu_cookie_session_de_aoc
AOC_BOARD=123456
# Opcional
AOC_YEAR=2024

¿De dónde saco AOC_SESSION?

  • Inicia sesión en https://adventofcode.com
  • Abre DevTools → Application/Storage → Cookies → session
  • Copia el valor

Importante:

  • No comitees .env.local.
  • La cookie da acceso a tu cuenta, trátala como un secreto.

Cómo correrlo

Instalar dependencias:

npm install

Modo desarrollo:

npm run dev

Abrir:

Build de producción:

npm run build
npm run start

Deploy en Vercel

  1. Importa el repo en Vercel (New Project → Import Git Repository).
  2. Configura estas Environment Variables (Project Settings → Environment Variables):
    • AOC_SESSION
    • AOC_BOARD
    • AOC_YEAR (opcional)
  3. Deploy.

Notas:

  • Este proyecto hace el fetch a AoC desde el backend (Route Handler). En Vercel, las env vars se inyectan en el runtime del servidor, así que no se exponen al cliente.
  • Hay un vercel.json con un cron apuntando a /api/daily-task. Si quieres usarlo como “warm up”, cambia ese path a /api/aoc o crea ese endpoint.

Troubleshooting rápido

  • ok: false / error 500 en /api/aoc:
    • Revisa AOC_SESSION (expirada o incorrecta)
    • Revisa AOC_BOARD (id del leaderboard)
    • Verifica que el año (AOC_YEAR) exista y que el board sea de ese evento

Nota sobre rate limiting

Este proyecto intenta ser “buen ciudadano” con AoC:

  • Backend cacheado 15 minutos.
  • Cliente revalida cada 15 minutos y al volver al foco.

Si quieres, también puedo añadir una sección de “Deploy en Vercel” basada en vercel.json y las env vars del proyecto.

Releases

No releases published

Packages

 
 
 

Contributors