
Hace poco compartí mi experiencia sobre cómo migrar una aplicación Vaadin sencilla con la ayuda de Claude AI. Esa experiencia demostró que la IA es excelente para desenredar código legacy, pero me dejó con una duda: ¿qué pasa cuando empezamos desde cero? Recientemente, mi equipo en Flowing Code propuso crear un nuevo add-on: un wrapper en Vaadin para el componente @github/relative-time-element. Esta vez, decidí integrar a Claude AI desde el minuto cero, usándolo no solo como un generador de código, sino como un compañero de diseño arquitectónico.
El resultado fue un desarrollo en tiempo récord, pero lo más valioso no fue la velocidad, sino el proceso. Aquí te cuento cómo pasamos de una idea a un componente funcional validando cada paso del camino.
La Especificación como Herramienta de Decisión
Normalmente, cuando alguien propone un add-on, la decisión de construirlo o no se basa en un “parece útil”. Esta vez, cambiamos las reglas.
Antes de escribir una sola línea de código, le pedí a Claude que leyera la documentación del paquete npm de GitHub y generara una especificación completa del wrapper en Java. El objetivo no era documentar un trabajo terminado, sino usar la especificación para decidir si valía la pena construirlo.
Claude elaboró un análisis detallado que incluía el mapeo de atributos, los enums de presentación y toda la estructura de la API.
Escribir la especificación con la ayuda de Claude es una forma increíblemente barata de convertir una propuesta vaga en un proyecto viable. Al ver la superficie de la API claramente definida, pudimos dar luz verde al proyecto con total confianza.
Ese documento se convirtió en el SPECIFICATIONS.md del repositorio, viviendo junto al código y sirviendo como nuestra fuente de verdad.
Automatiza lo Mecánico, Conserva el Juicio Humano
Para crear el add-on, usamos nuestro starter interno de creación de add-ons. Históricamente, adaptar este starter implicaba unos 30 minutos o más de trabajo tedioso: buscar y reemplazar nombres, actualizar pom.xml, ajustar las url y badges para el Vaadin Directory, etc.
Para evitar pedirle a Claude mediante un chat que hicirea estos reemplazos, creé un skill reutilizable de Claude. Este skill ejecutó toda la sustitución mecánica de variables en segundos.
Sin embargo, trazamos una línea muy clara:
- Lo que delegamos: Sustitución de texto en POM, README, plantillas de issues y actualización de cabeceras de licencia.
- Lo que mantuvimos manual: Renombrado de paquetes Java, configuración de temas y diseño de pruebas.
El skill se mantiene deliberadamente estrecho. Delegamos la parte cognitiva aburrida, pero las decisiones de estructura de proyecto quedan en manos del desarrollador.
El Flujo de Trabajo: Especificación → Plan → Código
Una vez configurado el repositorio, no le dije a Claude: “Construye esto basado en la especificación”. Esa es una receta para el desastre si el modelo alucina la arquitectura.
En su lugar, seguimos un enfoque de compromiso progresivo:
- Especificación: Define qué es.
- Plan de Implementación: Claude generó un desglose estructurado del trabajo (estructura de clases, enums, pruebas, demo).
- Código: Solo tras aprobar el plan, pasamos a la implementación real.
El plan es un piso, no un techo. La estructura inicial fue correcta, pero la mayor parte del valor del add-on surgió durante la iteración. Por ejemplo, refinamos el componente para que mantuviera el último Instant aplicado como la única fuente de verdad en el servidor, ya que el estado renderizado vive exclusivamente en el DOM del navegador.
El Verdadero Valor de un Wrapper: Fallar Rápido
Uno podría pensar que hacer un wrapper de un Web Component es simplemente pasar variables de Java a HTML. Pero al revisar el código de Claude contra el código fuente real en TypeScript de @github/relative-time-element (y no solo su README), descubrimos algo crucial.
En el navegador, el component base perdona muchos errores: si le pasas una zona horaria inválida o un umbral negativo, simplemente falla en silencio o renderiza mal sin avisar.
Ahí es donde el add-on en Java toma protagonismo. Le dimos a nuestro componente la responsabilidad de convertir esos fallos silenciosos en excepciones del lado del servidor:
- Validamos zonas horarias contra
ZoneId.getAvailableZoneIds(). - Rechazamos umbrales negativos (
Duration) con unIllegalArgumentException. - Validamos los estilos de los componentes de fecha.
El trabajo principal de un wrapper tipado en Java no es solo autocompletar código; es evitar que el navegador se pase por alto errores en silencio, haciendo que la aplicación falle rápido y de forma ruidosa en el servidor durante el desarrollo.
Compatibilidad y el costo de mantener dos temas (Vaadin 24 y 25)
Como Vaadin 25 incluye el nuevo tema Aura, tomamos la decisión de que nuestros add-ons debían soportar tanto Lumo como Aura si eran compatibles con Vaadin 25.
El componente Relative Time en sí es solo texto en línea (inline text) y no requiere CSS específico de ningún tema. Por lo tanto, el trabajo de diseño se limitó estrictamente a actualizar la demo para que pudiera mostrar el componente de forma correcta. En retrospectiva, las restricciones del entorno de la demo deberían haber estado explícitas en las specs. Como no lo fueron, el código generado dependía por completo de variables de Lumo , lo que obligó a hacer un retrabajo con Claude para implementar una cadena de fallbacks robusta que soportara Lumo, Aura y el tema Base, exactamente como espera nuestra demo online.
Desde el principio, un requisito fundamental era que el componente funcionara perfectamente tanto en Vaadin 24 como en Vaadin 25. Esto trajo consigo un desafío interesante durante la creación de las demos: la compatibilidad de temas. Los add-ons en Vaadin 25 deben soportar tanto Lumo como el nuevo tema Aura.
Conclusiones
Crear este add-on con Claude en el flujo de trabajo fue una revelación. Nos permitió movernos increíblemente rápido, pero con un nivel de rigor superior al habitual.
Mis principales lecciones de este experimento son:
- Usa a la IA para decidir, no solo para ejecutar: Generar la especificación primero te salva de proyectos sin futuro.
- Lee el código fuente, no el README: Para que un wrapper delgado sea robusto, necesitas entender el componente subyacente a nivel de código. La IA te asiste, pero la revisión cruzada es vital.
- Los humanos tienen la última palabra: La IA propone, el humano dispone y corrige.
Que Claude construyera este add-on me dio la ventaja de actuar como el arquitecto, permitiéndome planificar, iterar y validar a una velocidad sin precedentes. Si estás pensando en crear componentes para Vaadin, integrar un asistente de IA de forma metódica (Especificación → Plan → Código) es algo que definitivamente vale la pena explorar.
El resultado de todo este proceso ya está publicado. Si quieres probarlo en tus proyectos, el add-on RelativeTime ya está disponible en el Vaadin Directory y es 100% compatible con Vaadin 24 y Vaadin 25. También puedes experimentar con nuestro demo online. ¡Espero que les sea tan útil usarlo como lo fue para nosotros construirlo!
Gracias por leernos ¡and let’s keep the code flowing!
¡Únete a la conversación!