Next.js
React
TypeScript
Tailwind CSS
Vercel
Portafolio
Desarrollo Web

Cómo construí mi portafolio con Next.js y Vercel

Mouhssine Lakhili profile
Mouhssine Lakhili
12 de enero de 20256 min de lectura

Un análisis profundo de la creación de un portafolio de desarrollador moderno, rápido y optimizado para SEO con Next.js 13, TypeScript, Tailwind CSS y Vercel. Detallo decisiones de arquitectura, optimizaciones y buenas prácticas.

Cómo construí mi portafolio con Next.js y Vercel
Imagen de portada: Como Mouhssine Lakhili construyo un portafolio con Next.js, Vercel y una base SEO limpia.

Introducción

Como desarrollador full-stack, tener un portafolio profesional es esencial para mostrar tus habilidades a reclutadores y potenciales clientes. Después de evaluar varios frameworks y enfoques, elegí construir mi portafolio con Next.js 13, TypeScript y Tailwind CSS, y desplegarlo en Vercel.

En este artículo, te explico las decisiones clave, la arquitectura y las optimizaciones que hacen que este portafolio destaque. Ya sea que quieras crear tu propio portafolio o simplemente conocer prácticas modernas de desarrollo web, esta guía te dará información valiosa.

¿Por qué Next.js?

Next.js se convirtió en mi framework principal para aplicaciones React, y estas son las razones por las que es perfecto para un portafolio:

Renderizado del lado del servidor y generación estática

Next.js ofrece varias estrategias de renderizado listas para usar:

// Static Site Generation (SSG) - Ideal para portafolios
export async function generateStaticParams() {
  const posts = getAllPostSlugs();
  return posts.map((slug) => ({ slug }));
}

// Esta página se genera en build
export default function BlogPost({ params }: { params: { slug: string } }) {
  const post = getPostBySlug(params.slug);
  return <Article post={post} />;
}

Para un portafolio, la generación estática (SSG) es ideal porque:

  • El contenido no cambia con frecuencia
  • Las páginas cargan al instante (HTML pre-renderizado)
  • Excelente SEO (los motores pueden rastrear el contenido)
  • Costo de servidor cero (archivos estáticos)

Arquitectura App Router

Next.js 13 introdujo el App Router, que utilicé para una organización clara:

app/
+-- layout.tsx        # Layout raíz con providers
+-- page.tsx          # Página de inicio
+-- blog/
¦   +-- page.tsx      # Listado del blog
¦   +-- [slug]/
¦       +-- page.tsx  # Artículo individual
+-- globals.css

Este enrutamiento basado en archivos hace que la base de código sea intuitiva y mantenible.

TypeScript para seguridad de tipos

TypeScript no solo ayuda a evitar errores: también documenta el código y mejora el tooling:

// Definiciones de tipos para artículos
export type BlogPostFrontmatter = {
  title: string;
  description: string;
  author: string;
  date: string;
  tags: string[];
  coverImage: string;
  published: boolean;
  seoTitle?: string;
  seoDescription?: string;
};

export type BlogPost = {
  slug: string;
  frontmatter: BlogPostFrontmatter;
  content: string;
  readingTime: {
    text: string;
    minutes: number;
    words: number;
  };
};

Con estos tipos, mi IDE ofrece autocompletado, detecta errores y hace que el refactor sea seguro.

Estilos con Tailwind CSS

Elegí Tailwind CSS por su enfoque utility-first y su excelente experiencia de desarrollo:

// Componente limpio y legible con Tailwind
function ProjectCard({ project }: { project: Project }) {
  return (
    <div className="group relative overflow-hidden rounded-xl border border-border bg-card transition-all hover:shadow-lg">
      <div className="aspect-video relative">
        <Image
          src={project.image}
          alt={project.title}
          fill
          className="object-cover transition-transform group-hover:scale-105"
        />
      </div>
      <div className="p-6">
        <h3 className="text-xl font-bold text-foreground mb-2">
          {project.title}
        </h3>
        <p className="text-muted-foreground line-clamp-2">
          {project.description}
        </p>
      </div>
    </div>
  );
}

Variables CSS para el tema

Uso variables CSS para un sistema claro/oscuro robusto:

:root {
  --background: 0 0% 98%;
  --foreground: 215 25% 15%;
  --primary: 0 84% 60%;
  --muted: 215 20% 95%;
}

.dark {
  --background: 224 27% 6%;
  --foreground: 210 40% 95%;
  --primary: 0 90% 65%;
  --muted: 224 27% 12%;
}

Este enfoque permite un cambio de tema fluido sin lógica compleja.

Optimizaciones de rendimiento

El rendimiento es clave para la experiencia de usuario y el SEO. Esto es lo que implementé:

Optimización de imágenes

El componente Image de Next.js se encarga de optimizar automáticamente:

import Image from 'next/image';

<Image
  src={post.coverImage}
  alt={post.title}
  fill
  priority // Cargar imágenes above-the-fold inmediatamente
  sizes="(max-width: 768px) 100vw, 60vw"
  className="object-cover"
/>

División de código

Next.js divide el código por ruta, y además uso imports dinámicos:

import dynamic from 'next/dynamic';

// Cargar solo cuando sea necesario
const ProjectsSection = dynamic(
  () => import('@/components/sections/projects'),
  { loading: () => <ProjectsSkeleton /> }
);

Optimización de fuentes

next/font elimina el layout shift y optimiza la carga:

import { Syne } from 'next/font/google';

const syne = Syne({
  subsets: ['latin'],
  weight: ['400', '500', '600', '700', '800'],
  display: 'swap',
});

Implementación SEO

Para un portafolio, el SEO es crítico. Este es mi enfoque:

Metadatos dinámicos

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = getPostBySlug(params.slug);

  return {
    title: `${post.frontmatter.title} | Mouhssine Lakhili`,
    description: post.frontmatter.description,
    openGraph: {
      title: post.frontmatter.title,
      description: post.frontmatter.description,
      type: 'article',
      publishedTime: post.frontmatter.date,
      authors: [post.frontmatter.author],
    },
    twitter: {
      card: 'summary_large_image',
      title: post.frontmatter.title,
      description: post.frontmatter.description,
    },
  };
}

Datos estructurados (JSON-LD)

Agrego schema markup para resultados enriquecidos:

const jsonLd = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: post.frontmatter.title,
  description: post.frontmatter.description,
  author: {
    '@type': 'Person',
    name: 'Mouhssine Lakhili',
  },
  datePublished: post.frontmatter.date,
  image: post.frontmatter.coverImage,
};

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>

Generación automática del sitemap

Un script pre-build genera el sitemap:

// scripts/generate-sitemap.js
function generateSitemap() {
  const blogPosts = getBlogPosts();

  const urls = [
    { loc: SITE_URL, priority: '1.0' },
    { loc: `${SITE_URL}/blog`, priority: '0.8' },
    ...blogPosts.map(post => ({
      loc: `${SITE_URL}/blog/${post.slug}`,
      priority: '0.7',
      lastmod: post.date,
    })),
  ];

  // Generate XML...
}

Internacionalización (i18n)

Mi portafolio soporta inglés, francés y español:

const translations = {
  en: {
    'nav.home': 'Home',
    'nav.about': 'About',
    'nav.projects': 'Projects',
    // ...
  },
  fr: {
    'nav.home': 'Accueil',
    'nav.about': 'A propos',
    'nav.projects': 'Projets',
    // ...
  },
  es: {
    'nav.home': 'Inicio',
    'nav.about': 'Acerca de',
    'nav.projects': 'Proyectos',
    // ...
  },
};

Gracias a un contexto de React, el cambio de idioma es fluido y se mantiene entre sesiones.

Despliegue en Vercel

Vercel ofrece la mejor experiencia para despliegues con Next.js:

  1. Cero configuración: conectar el repo de GitHub
  2. Previsualizaciones: cada PR tiene su propia URL
  3. Edge network: contenido servido desde 100+ ubicaciones
  4. Analytics: monitoreo de rendimiento integrado
# Eso es todo lo que necesitas
vercel deploy

Puntos clave

Construir este portafolio me dejó varias lecciones importantes:

  1. Empezar con rendimiento en mente: es más fácil mantenerlo rápido que acelerar algo lento
  2. Tipar todo: TypeScript detecta bugs antes de llegar al usuario
  3. SEO desde el día uno: estructura el contenido temprano
  4. Accesibilidad: HTML semántico y ARIA
  5. Mantenerlo simple: evitar la sobre-ingeniería

¿Qué sigue?

Sigo mejorando este portafolio. Próximas mejoras:

  • RSS para el blog
  • Seguimiento de vistas
  • Integración de newsletter
  • Más componentes interactivos

Conclusión

Construir un portafolio es más que mostrar proyectos: es una oportunidad para demostrar tus habilidades en acción. Cada línea de código, cada decisión de diseño y cada optimización hablan de tus capacidades.

Si estás pensando en crear tu propio portafolio, te recomiendo empezar con Next.js. La experiencia de desarrollo es excelente, el rendimiento es sobresaliente y el ecosistema es sólido.

Puedes explorar mi GitHub, mi perfil o mi pagina freelance si tienes preguntas.


¿Quieres hablar sobre este artículo o tienes preguntas sobre cómo construir tu propio portafolio? Conectemos en LinkedIn o Twitter.

Articulos relacionados

Construir con IA y entregar bien

Necesitas un desarrollador capaz de llevar una idea a produccion?

Ayudo a equipos a entregar trabajo en React, Next.js, Node.js, IA y automatizacion con alcance claro, guardrails utiles y ejecucion rapida.

Compartir este artículo

Articulos relacionados