DEV Community

Joshua Terrones
Joshua Terrones

Posted on Originally published at josht.xyz

Conecté mi portafolio a APIs reales: GitHub, Hackatime y Sanity

Durante las últimas semanas estuve construyendo mi portafolio personal en Next.js 16. Al principio todo era maquetación pura: los proyectos mostraban "Proyecto 01, Proyecto 02, Proyecto 03", las horas de código decían "000h", y el blog era un array hardcodeado con tres posts de prueba. Un esqueleto precioso, pero vacío.

Esta semana decidí conectarlo todo a APIs reales. Este post es la bitácora completa del proceso, incluyendo los errores que me costaron más tiempo del que me gustaría admitir.

GitHub API: la primera integración

Lo primero que quise resolver era que la Home mostrara mis proyectos reales en lugar de placeholders. Después de investigar un poco descubrí algo importante: la API REST de GitHub no expone los repositorios "pinned" (los que eliges manualmente en tu perfil). Solo devuelve todos los públicos.

Para obtener los pinned reales hay que usar la API GraphQL, que sí permite consultar los pinnedItems de un usuario. Así que terminé con una arquitectura híbrida:

GraphQL → para los repos destacados en la Home.
REST → para el listado completo en /proyectos.
Ambas con caché de 24 horas vía next: { revalidate: 86400 }.

Hackatime: las horas que realmente programo

Hackatime es un fork abierto de WakaTime que usa Hack Club para trackear horas de código. Registra tus editors y te da estadísticas reales: cuántas horas programaste, qué lenguajes usas más, racha de días activos.

La API devuelve un JSON muy limpio. Un ejemplo real de mi cuenta, con el rango del año completo:

total_seconds: 45725 → 12h 42m
TypeScript: 43.29%
Other: 38.81%
XML: 18.6%

Solo necesité configurar el API key en .env.local y hacer un fetch con la fecha de inicio del año. Los datos se muestran en /sobre-mi con barras de progreso por lenguaje.

Sanity: el blog que ya no es un array

Esta fue la parte más larga. Mi blog originalmente era un archivo posts.ts con tres posts hardcodeados. Funcionaba, pero cada vez que quería publicar algo tenía que editar código, commitear y esperar el deploy.

Sanity es un CMS headless que se embebe dentro de tu propia app de Next.js. Escribes posts desde /studio, se guardan en sus servidores, y tu blog los lee vía queries GROQ.

Un detalle que casi me vuelve loco: al embeber el Studio en Next.js, el CORS por defecto solo permite localhost:3333 (el puerto del Studio independiente), no el 3000 de tu app. Hay que añadirlo explícitamente:

npx sanity cors add http://localhost:3000 --credentials

Ese flag --credentials es crítico. Sin él, el Studio puede cargar pero el login se queda en un bucle infinito porque el navegador no envía las cookies de sesión.

Lo que aprendí

Tres lecciones que me llevo de esta integración:

  1. La API REST de GitHub no sirve para repos pinned. Hay que usar GraphQL. Perdí una hora intentando resolverlo con REST antes de leer la documentación oficial.

  2. La caché no es opcional. Si cada visita hace un fetch a la API, revientas el rate limit en un día. Con revalidate: 86400 consumes 3 requests al día en vez de 3000.

  3. Los errores de CORS son silenciosos y confusos. El login de Sanity no daba ningún mensaje de error claro — solo un bucle infinito. La solución estaba en un flag de configuración que no aparece en el tutorial básico.

Lo que viene

Todavía queda trabajo: conectar este blog a Dev.to para publicar automáticamente, añadir un formulario de contacto con Resend, y eventualmente soporte bilingüe (español/inglés) con next-intl.

Pero por ahora, el portafolio ya no es un esqueleto. Muestra proyectos reales, cuenta las horas que programo de verdad, y tiene un blog que puedo actualizar sin tocar una sola línea de código.

Eso se siente bien.

Top comments (0)