Cuando empezamos a construir Kodeval, la primera pregunta técnica no fue qué framework usar. Fue si usar un framework. La respuesta, después de pensar un rato, fue no. Aquí explicamos por qué.
El problema con los frameworks hoy
Los frameworks modernos como React, Vue o Svelte resuelven problemas reales: estado reactivo, composición de componentes, routing del lado del cliente. Pero cuando los miras en contexto de un proyecto como Kodeval —un sitio estático con páginas mayormente de contenido y algo de interacción— el trade-off no cierra.
Un proyecto React típico arranca con un bundle de varios cientos de kilobytes antes de escribir una sola línea de código propio. Necesita un proceso de build, un entorno de Node, dependencias que se actualizan y rompen cosas, y un nivel de complejidad de tooling que no tiene razón de ser si tu sitio es esencialmente HTML con algo de JavaScript para interacción.
La complejidad debería ser proporcional al problema. Si el problema es simple, la solución debería serlo también.
Qué ganamos eligiendo vanilla
La ganancia más inmediata fue la velocidad. Sin proceso de build, sin bundler, sin tiempo de compilación. Un cambio en el HTML se ve al refrescar el navegador. En proyectos donde la iteración de diseño es frecuente, eso es un multiplicador real de productividad.
La segunda ganancia fue la durabilidad. HTML y CSS de 2015 sigue funcionando en 2026 sin tocar nada. No existe ese problema con React 16 cuando hoy estás en React 19. El HTML que escribimos hoy va a funcionar en 10 años sin que nadie tenga que hacer una migración.
Y la tercera, la que más importa para Kodeval Pages, fue la pedagógica: si tu producto es una librería de componentes que cualquiera puede copiar y pegar, ese código tiene que ser legible para cualquier desarrollador, independientemente de qué stack usa. Vanilla es el único lenguaje común.
Qué sacrificamos
No todo es positivo. El manejo de estado compartido es engorroso sin una librería. Para Kodeval, lo resolvimos con patrones simples: el estado de autenticación vive en auth.js y los componentes compartidos se inyectan en el DOM desde components.js. No es tan elegante como Context de React, pero funciona para nuestra escala.
Los componentes tampoco son reutilizables de la misma forma. En la práctica, duplicamos algunos bloques de CSS entre páginas. Lo mitigamos con variables CSS en :root y hojas de estilo compartidas, pero hay repetición que en un sistema de componentes no existiría.
- Sin hot reload real (solo recarga manual del navegador)
- Sin TypeScript nativo (errores de tipo en runtime, no en compilación)
- Sin tree-shaking (CSS sin usar se envía al cliente)
- El mantenimiento de los headers/footers requiere tocar el archivo JS manualmente
Cuándo tiene sentido hacer lo mismo
Esta decisión tiene sentido si tu proyecto cumple estas condiciones: el contenido es mayormente estático, la interactividad es limitada y conocida de antemano, la audiencia incluye desarrolladores que necesitan leer el código, y el equipo es pequeño y valora la simplicidad operativa.
Si estás construyendo una aplicación con estado complejo, muchas rutas dinámicas o un equipo grande que necesita tipado estricto, un framework probablemente sea la elección correcta. No hay respuesta universal.
Lo que hubiéramos hecho diferente
La única cosa que cambiaríamos es haber definido antes los tokens de diseño. Empezamos con variables CSS sueltas en cada página y recién después las centralizamos en base.css. Hubiese sido mejor tenerlo claro desde el primer día, aunque sea con un sistema mínimo de colores y espaciado.
En retrospectiva, la apuesta por vanilla fue correcta para Kodeval. El sitio es rápido, el código es legible y el costo de mantenimiento es bajo. Cuando algo no funciona, la causa suele ser obvia. No hay magia negra del compilador ni abstracciones que oculten el problema.
A veces la mejor herramienta es la que ya venía con el navegador.
When we started building Kodeval, the first technical question wasn't which framework to use. It was whether to use a framework at all. After thinking about it for a while, the answer was no. Here's why.
The problem with frameworks today
Modern frameworks like React, Vue or Svelte solve real problems: reactive state, component composition, client-side routing. But when you look at them in the context of a project like Kodeval (a static site with mostly content pages and a bit of interaction), the trade-off doesn't add up.
A typical React project starts with a bundle of several hundred kilobytes before you write a single line of your own code. It needs a build step, a Node environment, dependencies that update and break things, and a level of tooling complexity that makes no sense if your site is essentially HTML with some JavaScript for interaction.
Complexity should be proportional to the problem. If the problem is simple, the solution should be too.
What we gained by choosing vanilla
The most immediate gain was speed. No build step, no bundler, no compile time. A change in the HTML shows up when you refresh the browser. In projects where design iteration is frequent, that's a real productivity multiplier.
The second gain was durability. HTML and CSS from 2015 still work in 2026 without touching anything. You don't have that problem with React 16 when you're on React 19 today. The HTML we write today will work in 10 years without anyone having to run a migration.
And the third, the one that matters most for Kodeval Pages, was teaching: if your product is a component library anyone can copy and paste, that code has to be readable by any developer, whatever stack they use. Vanilla is the only common language.
What we gave up
Not everything is positive. Managing shared state is clunky without a library. For Kodeval, we solved it with simple patterns: authentication state lives in auth.js and shared components are injected into the DOM from components.js. It's not as elegant as React Context, but it works at our scale.
Components aren't reusable in the same way either. In practice, we duplicate some CSS blocks across pages. We mitigate it with CSS variables in :root and shared stylesheets, but there's repetition that a component system wouldn't have.
- No real hot reload (only a manual browser refresh)
- No native TypeScript (type errors at runtime, not at compile time)
- No tree-shaking (unused CSS is sent to the client)
- Maintaining headers and footers means editing the JS file by hand
When it makes sense to do the same
This decision makes sense if your project meets these conditions: the content is mostly static, interactivity is limited and known in advance, the audience includes developers who need to read the code, and the team is small and values operational simplicity.
If you're building an application with complex state, many dynamic routes or a large team that needs strict typing, a framework is probably the right choice. There's no universal answer.
What we would have done differently
The only thing we'd change is defining the design tokens earlier. We started with loose CSS variables on each page and only later centralized them in base.css. It would have been better to have it clear from day one, even with a minimal system of colors and spacing.
In hindsight, betting on vanilla was the right call for Kodeval. The site is fast, the code is readable and maintenance costs are low. When something breaks, the cause is usually obvious. There's no compiler black magic or abstraction hiding the problem.
Sometimes the best tool is the one that already came with the browser.