Por qué migré mi portfolio de HTML plano a Next.js

Enterate del próximo post
Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.

Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.
Mi portfolio arrancó como tres archivos: index.html, styles.css y main.js. Funcionaba. Y durante un buen rato eso fue suficiente.
El problema apareció cuando quise partir el JavaScript en módulos ES6. Escribí algo tan inocente como esto:
import { initThemeToggle } from "./theme.js";
import { initProjectModals } from "./projects.js";
initThemeToggle();
initProjectModals();Al abrir el index.html directo desde el explorador de archivos —con un file://— el navegador tiraba esto:
Access to script at 'file:///.../theme.js' from origin 'null'
has been blocked by CORS policyLa única forma de trabajar cómodo era levantar un servidor local, y en ese momento entendí que ya no estaba haciendo "una página HTML": estaba haciendo una aplicación sin las herramientas de una aplicación.
styles.css de 900 líneas.next/image se encarga del lazy loading y de servir el formato correcto.metadata y las Open Graph images generadas dinámicamente con next/og.El tipado es lo que más cambió mi forma de trabajar. Antes los proyectos vivían en un array suelto; ahora hay un contrato:
export interface Project {
id: number;
title: string;
description: string;
summary: string;
tech: string;
technologies: Technology[];
deployed: string;
repo: string;
}Si agrego un proyecto y me olvido del summary, el editor me lo marca antes de guardar. Parece poco hasta que te pasa la tercera vez.
El dark mode. Lo resolví con una clase dark-mode en el <body> y variables CSS: cada componente declara sus overrides con :global(body.dark-mode) dentro de su propio módulo.
:root {
--primary-color: #0d0d0d;
--bg-color: #fff;
--card-bg: #fff;
}
body.dark-mode {
--primary-color: #f6f6f6;
--bg-color: #181c22;
--card-bg: #23272f;
}Es simple y funciona, pero hay que tener cuidado con el flash de contenido sin estilar en el primer render del servidor: el <body> todavía no tiene la clase cuando el HTML llega al navegador.
Si tuviera que resumir toda la migración en una sola imagen, sería esta:

Lo que cambió no es la idea del sitio, es dónde vive cada cosa.
Habría empezado por definir las variables CSS y la estructura de carpetas antes de escribir el primer componente. Terminé refactorizando dos veces porque los colores estaban hardcodeados en lugares donde después necesité que cambiaran con el tema.
Migrar no es reescribir. Es mover la misma idea a un lugar donde pueda crecer.
Si estás en la misma situación —una página estática que empezó a pedir cosas de aplicación— la señal clara es esta: cuando te encontrás peleando con el navegador en vez de con tu propio código, ya es hora.