DEV Community

Joshua Terrones
Joshua Terrones

Posted on Originally published at josht.xyz

Cómo construí un portafolio con datos reales: 4 APIs en una semana

Durante meses tuve un portafolio bonito pero vacío. Los proyectos decían "Proyecto 01, Proyecto 02, Proyecto 03", las horas de código decían "000h" y el formulario de contacto no enviaba nada. Un esqueleto precioso que no le decía nada a nadie.

Este mes decidí cambiarlo. La meta: cero placeholders, todo con datos reales, todo automatizado. Lo que sigue es la bitácora de cómo conecté cuatro servicios distintos en una sola semana y lo que aprendí en el camino.

GitHub API: los proyectos que sí tengo

El primer cambio fue el más visible: que la Home mostrara mis repositorios reales. La API REST de GitHub no expone los repos "pinned" (los que eliges manualmente en tu perfil), así que tuve que usar la API GraphQL, que sí lo permite.

El resultado es una arquitectura híbrida: GraphQL para los proyectos destacados de la Home, REST para el listado completo en /proyectos. Ambas con caché de 24 horas para no golpear el rate limit.

Una cosa que aprendí: si cada visita hace un fetch a la API, revientas el límite en un día. Con revalidate: 86400 consumes 3 requests al día en vez de miles. La caché no es opcional.

Hackatime: las horas que realmente programo

Hackatime es un fork de WakaTime que usa Hack Club para trackear tu actividad en el editor. Registra cuántas horas programas al día, qué lenguajes usas más y mantiene una racha de días activos.

Conectarlo fue sencillo: una API key, un endpoint y listo. Ahora mi sección "Sobre mí" muestra las horas reales que he programado este año y un desglose por lenguaje. Es una forma más honesta de mostrar actividad que un texto genérico.

Sanity: el blog que dejó de ser un array

Esta fue la parte más larga. Mi blog originalmente era un archivo hardcodeado con tres posts de prueba. Cada vez que quería publicar algo tenía que editar código, commitear, esperar el deploy. Un proceso de 15 minutos por post.

Sanity es un CMS headless que se embebe dentro de tu propia app de Next.js. Escribes desde /studio, el contenido se guarda en sus servidores y tu blog lo lee vía queries GROQ. Es la diferencia entre editar un archivo y escribir como en Medium.

Dos detalles que me costaron tiempo: primero, el CORS. 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 con el flag --credentials.

Segundo, el canonical URL de Dev.to. Dev.to rechaza URLs con http:// (sin S). Si tu dominio está redirigiendo o usas localhost, la sincronización falla con un error 422 que no explica nada.

Resend: el formulario que ahora sí envía correos

Lo último fue conectar el formulario de contacto. Antes solo simulaba el envío — el botón cambiaba a "Enviado ✓" pero nada llegaba a ningún lado. Con Resend, ahora llegan mensajes reales a mi bandeja de entrada.

La ventaja de Resend es que se integra muy bien con dominios personalizados. Verificas tu dominio con unos registros DNS, y ya puedes enviar correos desde tu propia dirección. El correo sale desde hola@josht.xyz y va directo a mi iCloud.

Lo que aprendí

Tres cosas que me llevo de esta semana:

Primero, la caché no es un detalle opcional. Es la diferencia entre una app que escala y una que se cae en la primera hora.

Segundo, los errores de CORS son silenciosos y confusos. El login de Sanity me tuvo atrapado en un bucle infinito durante una hora. La solución estaba en un flag de configuración que no aparece en el tutorial básico.

Tercero, la automatización vale la pena. El tiempo que invertí conectando el webhook de Sanity a Dev.to se paga solo en el segundo post. Ya no copio y pego nada.

Qué viene

Ahora que el sistema funciona, quiero enfocarme en el contenido. Publicar un post por semana sobre lo que voy aprendiendo: APIs, arquitectura, decisiones técnicas. El blog ya no es una barrera, es un espacio donde puedo escribir sin fricción.

También quiero añadir soporte bilingüe (español/inglés) y on-demand revalidation para que los posts aparezcan al instante. Pero eso es otra semana.

Por ahora, el portafolio hace lo que debe hacer: muestra trabajo real, cuenta la historia de cómo lo construí y facilita que alguien me contacte. Todo lo demás es refinamiento.

Top comments (0)