Crear un portfolio con Next.js y Notion API usando ISR
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
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
- Ir a Integraciones de Notion
- Crear una nueva integración con el nombre Portfolio CMS
- Configurarla como Internal
- Copiar el token de integración
Ese token será nuestra clave de acceso a la API:
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:
- Abre la página en tu workspace
- En los tres puntos (arriba a la derecha), entra en Conexiones
- 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.
- En la página duplicada, configura el botón Actualizar
- Asegúrate de que tenga la acción Enviar webhook
- Configura la URL:
- Agrega el header personalizado:
El secret puedes generarlo aquí: Online UUID Generator Tool
En desarrollo local, este paso no es necesario.

Paso 3: Variables de entorno
Obtener los IDs de las bases de datos
Para cada base de datos:
- Ábrela en Notion
- Ve a Configuración
- Entra en Gestionar fuentes de datos
- Copia el ID de la fuente


Crea un archivo .env.local con lo siguiente:
Ejecutar el proyecto
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
- Subir el proyecto a GitHub
- Importarlo en Vercel
- Configurar las variables de entorno
Las variables son las mismas que en .env.local:
Cómo funciona ISR en este proyecto
El sitio se genera de forma estática y solo se actualiza cuando yo lo decido.
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

Agregar nuevas secciones
Cuando necesito una nueva sección:
- Creo una nueva base de datos en Notion
- Agrego el fetch en
lib/data/ - 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í.