Construyendo un Portafolio Web: Experiencias con Diferentes Tecnologías e IA
Sin meterme en el tema de si es recomendable o no tener un portafolio, me gustaría compartir la experiencia que he tenido al desarrollar este último. Es la cuarta iteración que he hecho a lo largo de tres años, y cada versión me ha enseñado algo interesante. Antes de meterme en los detalles de la versión actual, voy a repasar las iteraciones anteriores, ya que estas me ayudaron a definir los requisitos que acabarían dando forma a la versión final.
El Camino Hacia un Portafolio Funcional
Los Primeros Pasos: Python y Flask
Mi primera web la construí con Python y Flask antes de entrar a la FP. Esta versión tenía dos problemas fundamentales que la hacían poco práctica en la realidad:
- Flask, siendo una tecnología de servidor, presentaba algunos inconvenientes. No es que Flask sea un problema en sí mismo - es una herramienta excelente para lo que está diseñada - pero para un portafolio resulta excesiva. Podría haber agregado plugins para gestionar el contenido y no tener que desplegar nuevamente cada vez que actualizaba los proyectos, pero aún así no parecía una solución a largo plazo.
- Las opciones para desplegar online y gratis no valían la pena o simplemente ya no existen. Inicialmente utilizaba la capa gratuita de Heroku, pero la página tardaba una eternidad en cargar y el servidor fallaba cada pocos días, obligándome a instalar todo y desplegar de nuevo. La gota que derramó el vaso vino cuando Heroku eliminó su capa gratuita, aparentemente porque algunos usuarios abusaban del servicio encadenando varias cuentas en lugar de pagar. Los servicios alternativos que probé eran incluso más lentos. La lección fue clara: hoy en día no es práctico depender de servidores si realmente no los necesitas.
Experimentando con WordPress
WordPress, el CMS que seguramente no necesite presentar, fue mi siguiente intento. Muchas de las webs que visitamos diariamente están gestionadas con esta tecnología, y por algo será. Sin embargo, para mis necesidades específicas, presentaba varios inconvenientes:
- Nuevamente, nos topamos con la dependencia de servidores. Desplegar la versión open-source no era práctico para un portafolio, y la versión gratuita, aunque servía para salir del paso, dejaba mucho que desear en cuanto a rendimiento.
- Las opciones de personalización de estilos y maquetación me parecían muy limitadas, y tenían demasiado "boilerplate". Y para el uso que quería darle a la web, tenía demasiados plugins instalados que no iba a utilizar.
No obstante, hubo algo que me encantó: tener un gestor de contenido. Me recordó a los buenos tiempos de Blogger y resolvía el problema que tenía con Flask de tener que hacer todo manualmente.
Definiendo los Requisitos Clave
De estas experiencias iniciales, pude extraer varios requisitos fundamentales:
- La página tenía que ser estática
- Debía tener un rendimiento óptimo
- Necesitaba contar con un gestor de contenido
- El frontend debía ser fácil de mantener
Con estos requisitos claros, me embarqué en la búsqueda de tecnologías que encajaran con mis necesidades. Es una cuestión de sentido común: es más eficiente usar una herramienta diseñada para el tipo de desarrollo que buscas que forzar las herramientas que conoces a cumplir requisitos para los que no están pensadas.
La Evolución: Strapi y Next.js
La solución que encontré fue dividir el proyecto en dos partes: un backend con un CMS minimalista (Strapi) y un frontend que pudiera generar páginas estáticas. Investigando (aunque no lo suficiente, como descubriría más tarde), me encontré con tres candidatos: Hugo, Next.js y Astro.
La Experiencia con Strapi
Strapi resultó ser una grata sorpresa. Si has trabajado con WordPress, la consola de administración de Strapi te resultará increíblemente intuitiva. El proceso es simple: creas tus tipos de contenido (individuales o colecciones), les añades los elementos necesarios (texto, multimedia, etc.), y puedes relacionarlos entre sí. Todo esto respaldado por una base de datos SQLite o PostgreSQL, según prefieras.
La interacción con los datos se gestiona a través de permisos de usuario y API REST. Aunque estoy usando Strapi 4, recomiendo empezar directamente con la versión 5 para proyectos nuevos, ya que incluye mejoras significativas en componentes básicos y un soporte para GraphQL mejorado.
La Aventura con Next.js
Elegí Next.js inicialmente por su extensa documentación y abundancia de tutoriales. Sin embargo, aquí es donde comenzó mi experiencia más significativa con la IA en el desarrollo, pero de eso hablaré más adelante.
Cometí dos errores cruciales:
- No hacer un prototipo temprano que incluyera todos mis requisitos y no realizar pruebas a las funcionalidades que podrían dar más problemas al inicio del proyecto.
- Confiar demasiado en tutoriales y IA sin leer a fondo la especificación del framework, y sus limitaciones.
Perdí tres semanas implementando una web que, contrario a mis intenciones, no era realmente estática. Cuando finalmente entendí el problema, invertí otra semana intentando convertir el proyecto a uno verdaderamente estático.
Una vez había dejado de utilizar Next.js, encontré algo que me dio bastante qué pensar al respecto sobre lo mucho que tenemos que entender los frameworks que utilizamos, en este caso Next.js pertenece a Vercel, que si no sabéis, es una plataforma de hosting, si lo resumimos de forma muy general. Next.js funciona mejor cuando utilizas Vercel que cuando lo quieres utilizar por tu cuenta, en mi caso no es sólo que el framework no estuviera pensando para generar contenido estático al 100%, es que además al intentar hacerlo no dejaba de tener que hacer parches en diferentes niveles de la aplicación y no lograba cumplir los requisitos al 100%. Os recomiendo ver este vídeo para que entendáis de lo que estoy hablando.
La Solución Final: Astro
Finalmente llegamos al segundo componente de este portafolio. Astro no es tan diferente a Next.js si hablamos de forma muy general - es un framework para crear webs o para mantener el enrutamiento, según como lo quieras ver. Porque realmente, según de las dependencias y herramientas que utilices, estas soluciones pueden ser un todo en uno o simplemente un módulo base.
Por ejemplo, Astro es compatible con React, Vue y otros frameworks, pero también implementa su propia forma de crear componentes. Puedes reemplazar el enrutamiento que ofrece con otro paquete, y así sucesivamente. Lo que me convenció fue que estaba mejor documentado que Hugo y podía mantener todas las funcionalidades que necesitaba, incluyendo algunas que no había mencionado antes, como un paquete nativo para implementar internacionalización.
Esta vez, aprendiendo de mis errores anteriores, desde el minuto cero implementé un prototipo que incluía todas las funcionalidades que tenía en mente. Hice un build local y lo desplegué en un servidor HTTP básico. Sólo cuando conseguí que todo funcionara (porque empaquetar algunos ficheros también requirió darle bastantes vueltas al tema), me lancé a desarrollar toda la web.
Para la implementación final, utilicé:
- Páginas y componentes de Astro para generar el contenido estático y el enrutamiento
- React para el reproductor de música, específicamente el paquete 'react-h5-audio-player' y para renderizar el bloque de texto enriquecido de Strapi
- Prism.js para colorear el código
- Otras dependencias menores para funcionalidades específicas
La Experiencia con IA: Una Reflexión Crítica
Como mencioné anteriormente, la calidad de los resultados en los buscadores ha bajado considerablemente, lo que hace que encontrar recursos útiles más allá de la documentación oficial sea cada vez más tedioso, especialmente cuando no estás familiarizado con las herramientas que estás utilizando.
Utilizando LLMs
Durante el desarrollo con Next.js, decidí apostar fuerte por la IA. Comencé con ChatGPT, pero incluso con una cuenta de pago, la calidad de sus respuestas había disminuido notablemente. Me cambié a Claude, que funcionaba mejor, pero seguía cayendo en problemas similares:
- Pérdida del contexto frecuente
- Repetición de soluciones que ya habían demostrado no funcionar
- Tendencia a volver a sugerencias descartadas después de unos pocos mensajes
Un Cambio de Perspectiva
Hasta entonces, había utilizado los LLMs como un "chatbot glorificado" para tareas específicas como las siguientes:
- Generar datos de prueba a partir de DDL de bases de datos
- Crear XML básico desde XSD
- Escribir boilerplate con implementaciones de referencia
- Traducir o compactar documentación
Sin embargo, al no conocer JavaScript en profundidad, mi dependencia de los LLMs aumentó considerablemente. Ya no estaba yo al mando - estaba sujeto a la calidad variable de las respuestas que recibía. En retrospectiva, el tiempo que pensaba ahorrar no fue tal. Si hubiera invertido ese tiempo en aprender JavaScript adecuadamente, probablemente habría terminado el proyecto en el mismo tiempo.
Lecciones Sobre el Uso de IA en Desarrollo
Es importante aclarar: si lo que quieres crear es una aplicación común, no tendrás muchos problemas con la IA. Pero cuando tus requisitos se vuelven más específicos o el proyecto crece - como en este caso con internacionalización, generación de rutas en tiempo de build, componentes basados en API, empaquetado de multimedia - el proyecto ya no es el mismo bloque monolítico de antes. Y aquí es donde empiezamos a rozar los límites de lo que puede manejar un LLM sin empezar a alucinar cada dos o tres mensajes.
¿Se puede hacer? Claro que sí. ¿Deberías? En mi caso, creo que no. No solo he tenido que invertir mucho tiempo, sino que al final no he aprendido tanto como esperaba. Probablemente, si no hubiera dependido tanto de la IA, habría notado antes los fallos que me encontré en la versión de Next.js.
Reflexiones Finales
Esta experiencia me ha llevado a algunas conclusiones importantes:
- Sobre el Desarrollo: Da igual con qué herramienta trabajes y lo mucho que creas que sabes - hay que estudiar bien cómo funcionan las cosas y hacer prototipos pequeños que implementen todos los requisitos posibles. Esto nos asegura que el tiempo que vamos a invertir lo estamos poniendo en una herramienta capaz de resolver nuestro problema.
- Sobre la IA: Voy a limitar el uso de la inteligencia artificial, en particular de los LLMs, lo máximo posible. Su uso será el que le daba hace casi dos años: boilerplate, boilerplate, boilerplate, y siempre para cosas muy concisas y específicas.
- Sobre el Estado Actual de la IA: Los avances significativos parecen hacerse más por fuerza bruta que por mejoras fundamentales en los modelos. Si las mejoras técnicas están subordinadas a entrenar con más y más datos, sin ofrecer un retorno igualmente sustancial, entonces lo que nos están vendiendo hoy podría ser más humo que realidad.
Espero que algo de lo que he compartido aquí te resulte útil en tu propio viaje de desarrollo. A veces, los mayores aprendizajes vienen de nuestros tropiezos y de estar dispuestos a cuestionar nuestras propias suposiciones sobre las herramientas que utilizamos.
PS: La canción que utilicé para el reproductor la encontrarás aquí. Sobre el shader que visualiza el audio, lo hice utilizando shader-toy, utilizando este tutorial como referencia principal. Quizás escriba una entrada de blog sobre el tema cuando sepa más sobre visualización de audio y shaders.