← Volver al blog
·5 min de lectura

Construyendo un portafolio profesional con Next.js y Tailwind CSS

Next.jsTailwind CSSFrontend

Por que Next.js para un portafolio

Cuando decidi reconstruir mi portafolio profesional, evalue varias opciones: un sitio estatico puro con HTML y CSS, frameworks como Astro o Gatsby, y finalmente Next.js. La decision no fue trivial — cada opcion tiene sus ventajas.

Lo que inclino la balanza hacia Next.js 15 fue la combinacion de varios factores:

  • App Router y Server Components: Permiten una arquitectura donde el servidor hace el trabajo pesado y el cliente recibe HTML listo para renderizar
  • Exportacion estatica: Con output: "export" en produccion, el sitio se genera como archivos HTML estaticos que se sirven desde cualquier servidor sin necesidad de Node.js
  • Ecosistema maduro: TypeScript de primera clase, optimizacion de imagenes, metadata API para SEO y un sistema de rutas basado en el filesystem

La alternativa mas cercana era Astro, que tambien genera sitios estaticos. Sin embargo, Next.js me ofrecia familiaridad (lo uso profesionalmente con Liferay DXP) y la flexibilidad de escalar a funcionalidades dinamicas si las necesitara en el futuro.

Arquitectura del proyecto

El sitio sigue una estructura deliberadamente simple:

src/
  app/           # Rutas (App Router)
  components/    # Componentes React reutilizables
  data/          # Datos estaticos tipados
  lib/           # Utilidades y logica de negocio
content/
  blog/          # Articulos en Markdown
public/          # Assets estaticos

Cada seccion del portafolio es un Server Component independiente. No hay estado global, no hay context providers innecesarios, no hay librerias de estado. La mayoria de componentes son funciones puras que reciben props y renderizan HTML.

Los unicos Client Components ("use client") son los que genuinamente necesitan interactividad:

  • Navegacion: Detecta scroll para cambiar la apariencia del header
  • Tema oscuro/claro: Toggle que persiste la preferencia en localStorage
  • Animaciones de entrada: Un componente Reveal que usa IntersectionObserver para animar elementos cuando entran al viewport

Sistema de temas con CSS custom properties

En lugar de usar las utilidades de temas de Tailwind directamente, opte por un sistema basado en CSS custom properties (variables CSS). Esto permite cambiar el tema sin regenerar clases:

:root {
  --theme-bg: #0e0d0c;
  --theme-text: #ece6df;
  --theme-accent: #c9553d;
}

:root.light {
  --theme-bg: #f5f0eb;
  --theme-text: #1a1614;
}

Las variables se mapean a tokens de Tailwind via @theme inline, lo que permite usar clases como bg-bg, text-text-secondary o border-border directamente en los componentes. El cambio de tema es instantaneo porque solo se actualiza la clase del elemento <html>.

La paleta de colores sigue una jerarquia clara: text para contenido principal, text-secondary para parrafos, text-tertiary para metadatos, y text-muted para elementos decorativos. El color accent (#c9553d, un terracota calido) se usa estrategicamente en CTAs, labels y hover states.

Tipografia con proposito

El sitio usa dos familias tipograficas cargadas con next/font/google:

  • Outfit (sans-serif): Para el cuerpo de texto. Pesos 300-600 cubren desde texto sutil hasta enfasis fuerte
  • Newsreader (serif): Exclusiva para headings y el logotipo. El contraste entre serif e italica crea identidad visual sin necesidad de un logo grafico

Los tamaños usan clamp() para ser responsivos sin media queries:

font-size: clamp(32px, 5vw, 48px);

Esto garantiza que los titulos se vean bien tanto en un iPhone SE como en un monitor ultrawide, sin saltos abruptos entre breakpoints.

Rendimiento y SEO

Con la exportacion estatica, cada pagina se pre-renderiza como HTML en tiempo de build. El resultado son archivos que se sirven directamente desde Nginx sin procesamiento del lado del servidor. Esto tiene implicaciones directas en rendimiento:

  • Time to First Byte (TTFB): Minimo, porque Nginx sirve archivos estaticos
  • Largest Contentful Paint (LCP): Optimizado con priority en imagenes above the fold
  • Cumulative Layout Shift (CLS): Zero, porque los tamaños de imagen y fuentes estan definidos

Para SEO, el sitio incluye:

  • Metadata API de Next.js: Cada pagina define title, description, OpenGraph y Twitter cards
  • JSON-LD: Schema.org Person en el layout root, BlogPosting en cada articulo
  • Sitemap dinamico: Se genera automaticamente incluyendo todas las paginas y posts del blog
  • RSS feed: Para que los lectores puedan suscribirse al contenido

Animaciones sin JavaScript innecesario

Las animaciones de entrada usan dos tecnicas:

  1. CSS keyframes para el hero (no depende de JS para la animacion, solo para el timing)
  2. IntersectionObserver via el componente Reveal para el resto de secciones

El patron del Reveal es simple: el elemento inicia con opacity: 0 y translateY(20px). Cuando entra al viewport, una transicion CSS lo lleva a su estado final. El delay se pasa como prop para crear efectos stagger entre elementos de una lista.

Conclusiones

Construir un portafolio no requiere un stack complejo. Next.js con exportacion estatica, Tailwind CSS para estilos utilitarios, y un par de componentes bien pensados producen un sitio rapido, accesible y facil de mantener. La clave esta en tomar decisiones conscientes sobre que complejidad agregar y cual evitar.

El codigo fuente de este portafolio esta disponible en mi perfil de GitHub. Si tienes preguntas sobre alguna decision tecnica, no dudes en contactarme.