poesía.pics - ¿qué hay de nuevo?
recientemente he estado trabajando en una nueva versión de poesía.pics. quería dejar de lado el antiguo stack y probar nuevas tecnologías. a continuación escribo sobre la experiencia
versiones anteriores
v1 - blip & gpt3
la primera versión de poesia.pics tuvo una aproximación más serverless. consistía en un servicio construido en adonisjs, usando supabase para la base de datos y almacenamiento de las imágenes, desplegado en google cloud run. para la generación de poemas usaba dos modelos:
- blip: para obtener una descripción de la imagen
- gpt3 para convertir la descripción en un poema
como puedes imaginar, los poemas que se generaban carecían de mucho contexto porque las descripción de blip son cortas y muy generales.
v2 - gpt4o
la segunda versión mejoró mucho la calidad porque empecé a usar gpt4o, enviando directamente la imagen al modelo y así aprovechar al máximo sus capacidades visuales.
además, me uní al movimiento de usar tu propia infraestructura, migrando el servicio desde google cloud run a mi propia máquina virtual. seguí usando adonisjs pero el almacenamiento de archivos estaba ahora estaría en un volumen de docker. otro cambio significativo que ayudó a la velocidad fue usar sqlite (que también se almacenaba en mi propia máquina) en vez de postgres (supabase)
v3
y llegamos a la versión 3, la más reciente y por la que más me siento emocionado. esta nueva versión incluye la completa re-escritura de la plataforma y una mejora significativa en el perfomance de la misma.
¿qué hay de nuevo? ¿qué ha cambiado?
1. bye, bye adonis, hola nuxt
el cambio más importante fue la re-escritura de la plataforma en nuxt. como mencioné anteriormente poesía.pics estuvo escrita desde el principio en adonisjs y aunque adonis es un framework que en lo personal considero muy fácil de aprender y usar y te da todo lo que necesitas para montar casi cualquier servicio desde cero, resultaba muy sobrecargado para lo que realmente usaba en poesía.pics.
para poesía.pics solo necesitaba 1) una conexión a db 2) un frontend que consistía en dos páginas 3) poder recibir archivos. así que me puse en búsqueda de alguna alternativa más liviana y volví a un viejo conocido: nuxt
flowchart LR
subgraph VPS
subgraph Docker
subgraph containers
nuxt@{icon: 'ph:heart-fill', label: 'Nuxt App'}
end
subgraph volumes
db.sqlite@{icon: 'ph:database', label: 'db.sqlite'}
volume@{icon: 'ph:folder-notch-open', label: 'Uploads'}
end
nuxt --> db.sqlite
nuxt --> volume
end
end
openai@{icon: 'ph:open-ai-logo', label: 'GPT-4o'}
user@{ icon: 'ph:user', label: 'User' }
nuxt -.-> openai
user --> nuxt
style VPS fill:transparent
style Docker fill:transparent
style containers fill:transparent
style volumes fill:transparent
pero, ¿por qué nuxt?
- tengo mucha experiencia con vue y es el framework ui que más me gusta
- nuxt provee ssr
- con nuxt puedes construir aplicaciones full-stack :p
- y por último: nuxt ui. una librería de componentes para vue/nuxt que le permite a alguien como yo, una persona con pocas habilidades en la materia del desarrollo web, tener una aplicación más o menos presentable con muy poco esfuerzo
y vaya que se notan los cambios, sobretodo en la velocidad de respuesta del sitio. por ejemplo, a continuación están los resultado de PageSpeed Insights para el nuevo sitio vs el antiguo
2. drizzle en vez de lucid
ahora, al dejar de usar adonisjs, perdía una de sus funcionalidad más atractivas: lucid js, su propio query builder y active record ORM. así que debía buscar una alternativa para conectarme y consumir la base de datos. aunque una cosa era clara: seguiría usando sqlite porque 1) había funcionado para la versión anterior 2) no requería ninguna característica de posgres o cualquier otro motor de base de datos
entonces, ahora que debía buscar una alternativa que soportara sqlite, me topé con drizzle orm. un amigo cercano lo usó y me lo recomendó, además ha ganado bastante popularidad en el mundo de node/js. así que me dispuse a leer su documentación y su aproximación simple para la definición de esquemas y queries me pareció muy bonita.
realmente fue fácil migrar los modelos y las migraciones de adonisjs. además, las peticiones a la base de datos ahora son unas decenas de milisegundos más rápidas
3. nuxt ui
quería mencionar también a nuxt ui, porque creo que una herramienta muy útil para solo-developers y equipos en general. al usar tailwindcss 4 la personalización se vuelve muy fácil y la variedad de componentes que ofrecen en la versión pro simplicaron mi trabajo.
4. un mejor seo
nuxt ofrece varios composables y componentes enfocados en el manejo del SEO de tu aplicación y fue algo que traté de aprovechar al máximo.
además, usé nuxt seo, un conjunto de librerías que me permitieron generar, por ejemplo, imágenes og usando un par de líneas de código:
defineOgImageComponent("Frame", {
title: "💖 poesia.pics",
description:
"Transforma tus fotografías en hermosos poemas utilizando Inteligencia Artificial. Sube una imagen y descubre la poesía que esconde.",
bg: "linear-gradient(to bottom right, #ff637e, #c70036)",
});

5. nueva página de poemas
para esta nueva versión quería aprovechar más el espacio horizontal en las pantallas de escritorio:

en comparación a la versión anterior, donde todo el layout fluía en el eje vertical sin importar si se visualizaba en escritorio o móviles:

6. un mejor prompt
esta versión usa un prompt más completo con respecto al anterior y desde las pruebas empíricas que he realizado noto una mejor calidad y profundidad en los poemas. pero bueno, tal vez sea algo personal. el prompt lo puedes encontrar en: krthr/poesia.pics/server/ai/prompt.ts
cosas que aún faltan
- filtro nsfw. creo que esta es la funcionalidad más urgente para evitar problemas con openai & hetzner (y tal vez hasta la ley)
- múltiples idiomas. una ventaja de los grandes modelos del lenguaje es que hablan muchos idiomas. poesía.pics podría generar poemas en varios idiomas usando una variedad distinta de escritores para tener un estilo propio en cada lengua.
- soporte de archivos HEIF. aún no he dado en el clavo con el soporte de archivos heic usando sharp y libvips. he pasado un par de horas tuneando el
dockerfile, pero cuando no es una cosa es otra. en el futuro próximo planeo dedicarle más tiempo a este problema. - tener un repositorio amigable con el open-source. aunque el código de poesía.pics está disponible en github, aún no he dedicado trabajo para mejorar el
READMEy dejar el repositorio listo para que otras personas puedan aportar. además, seguro hay un par de anti-patrones por ahí rondando en el código. - monetización. tengo un par de ideas que quiero implementar para experimentar con la monetización de la plataforma. aunque no es urgente ni necesario, creo que hay varias funcionalidades que podría ofrecer a cambio un par de dólares ;)
- ampliar la selección de poetas usados como inspiración. actualmente el prompt usado para generar los poemas usa una lista pequeña de poetas reconocidxs como inspiración artística. en el futuro me gustaría recibir feedback de la gente y así ampliar la lista de nombres. incluso, sería interesante usar diferentes poetas para los distintos "moods"
¡gracias por leer y usar poesia.pics!
un abrazo, wilson