Crear un portfolio con Next.js y Notion API usando ISR

Next.jsNotion APIISRPortfolio

Guía paso a paso para crear un portfolio moderno con Next.js y Notion API, usando Incremental Static Regeneration (ISR) para obtener un sitio rápido, escalable y fácil de mantener.

Publicado por Felipe Giraldo


En este post quiero mostrar cómo construí mi portfolio personal usando Next.js 16, Notion como CMS headless y Incremental Static Regeneration (ISR).

La idea era simple: tener un sitio rápido, fácil de mantener y que me permitiera actualizar el contenido sin tocar código cada vez.

Este enfoque es el que actualmente uso en mi portfolio y en varios proyectos con clientes.


¿Qué vamos a construir?

Un portfolio personal con las siguientes características:

  • Next.js 16 usando App Router
  • Notion API como gestor de contenido
  • Incremental Static Regeneration (ISR)
  • TypeScript
  • Tailwind CSS
  • Despliegue en Vercel

Prerrequisitos

Para seguir este tutorial necesitas:

  • Node.js 18 o superior
  • pnpm (recomendado), aunque npm o yarn también funcionan
  • Una cuenta de Notion
  • Una cuenta de Vercel

Paso 1: Configuración inicial del proyecto

Voy a partir de un template que ya tiene la estructura base del proyecto.

Clonar el repositorio

git clone https://github.com/astrxnomo/portfolio-nextjs-notion.git
cd portfolio-nextjs-notion
pnpm install

Antes de ejecutar el proyecto, es necesario configurar Notion y las variables de entorno.


Paso 2: Usar Notion como CMS

Una de las razones por las que uso Notion es porque me permite actualizar contenido de forma muy cómoda, sin paneles de administración adicionales.

Crear la integración en Notion

  1. Ir a Integraciones de Notion
  2. Crear una nueva integración con el nombre Portfolio CMS
  3. Configurarla como Internal
  4. Copiar el token de integración

Ese token será nuestra clave de acceso a la API:

NOTION_API_KEY=tu_token_de_integracion

Duplicar las bases de datos

Para no crear todo desde cero, puedes duplicar la plantilla con las bases de datos ya configuradas:

Una vez duplicada:

  1. Abre la página en tu workspace
  2. En los tres puntos (arriba a la derecha), entra en Conexiones
  3. Conecta la integración Portfolio CMS

Al hacer esto, la integración tendrá acceso a todas las bases de datos dentro de esa página.


Configurar el botón de actualización (ISR manual)

En producción, el sitio no se actualiza automáticamente. Yo prefiero tener control total sobre cuándo publicar cambios, así que uso un botón en Notion.

  1. En la página duplicada, configura el botón Actualizar
  2. Asegúrate de que tenga la acción Enviar webhook
  3. Configura la URL:
https://tu-dominio.vercel.app/api/revalidate
  1. Agrega el header personalizado:
X-Notion-Secret: TU_SECRETO_WEBHOOK

El secret puedes generarlo aquí: Online UUID Generator Tool

En desarrollo local, este paso no es necesario.

Image

Paso 3: Variables de entorno

Obtener los IDs de las bases de datos

Para cada base de datos:

  1. Ábrela en Notion
  2. Ve a Configuración
  3. Entra en Gestionar fuentes de datos
  4. Copia el ID de la fuente
Image
Image

Crea un archivo .env.local con lo siguiente:

NOTION_API_KEY=tu_token_de_integracion
NOTION_ABOUT_DB_ID=tu_id_base_about
NOTION_EXPERIENCE_DB_ID=tu_id_base_experience
NOTION_PROJECTS_DB_ID=tu_id_base_projects
NOTION_WEBHOOK_KEY=tu_secreto_webhook

Ejecutar el proyecto

pnpm dev

Luego abre http://localhost:3000.


Paso 4: Cargar tu contenido en Notion

About

Aquí coloco la información personal:

  • Nombre
  • Bio
  • Ubicación
  • Email
  • Redes
  • Skills

Experience

Uso esta base para mi experiencia laboral:

  • Empresa
  • Rol
  • Fechas
  • Descripción
  • Enlace externo

Projects

Aquí agrego los proyectos que quiero mostrar:

  • Nombre
  • Descripción
  • Imágenes
  • Demo y repositorio
  • Tecnologías

Paso 5: Despliegue en Vercel

  1. Subir el proyecto a GitHub
  2. Importarlo en Vercel
  3. Configurar las variables de entorno

Las variables son las mismas que en .env.local:

NOTION_API_KEY=tu_token_de_integracion
NOTION_ABOUT_DB_ID=tu_id_base_about
NOTION_EXPERIENCE_DB_ID=tu_id_base_experience
NOTION_PROJECTS_DB_ID=tu_id_base_projects
NOTION_WEBHOOK_KEY=tu_secreto_webhook

Cómo funciona ISR en este proyecto

El sitio se genera de forma estática y solo se actualiza cuando yo lo decido.

export default async function HomePage() {
  const { about, experience, projects } = await getData()
}

Qué gano con este enfoque

  • Mejor rendimiento
  • Páginas servidas desde CDN
  • SEO completo
  • Control total sobre publicaciones

Cuándo se actualiza el contenido

  • En local: cada cambio en Notion se refleja automáticamente
  • En producción: solo cuando presiono el botón Actualizar en Notion

Personalización

Estilos y colores

Los estilos están centralizados en app/globals.css.

También puedes usar TweakCN para ajustar el theme de Tailwind

Image


Agregar nuevas secciones

Cuando necesito una nueva sección:

  1. Creo una nueva base de datos en Notion
  2. Agrego el fetch en lib/data/
  3. Creo el componente en components/sections/

Problemas comunes

Invalid API key

  • Revisa el token
  • Confirma que la integración sea Internal

Database not found

  • Revisa los IDs
  • Asegúrate de que la base esté conectada a la integración

Conclusión

Este setup me permite tener un portfolio rápido, limpio y fácil de mantener, sin depender de un CMS tradicional.

Notion se convierte en el panel de administración y Next.js se encarga del rendimiento.

Es una base sólida que también uso para blogs, landings y sitios de clientes.

En los próximos posts puedo mostrar cómo:

  • Convertir esto en un blog completo
  • Manejar múltiples idiomas con Notion
  • Usar esta arquitectura para proyectos comerciales

Si te interesa alguno de esos temas, seguimos por ahí.