De Idea a App con AI Studio y Antigravity: construyendo una herramienta para freelancers

Tabla de contenidos

🚀 ¿Qué estamos construyendo y por qué importa?

La meta es simple pero potente: una aplicación que ayude a freelancers a ganar proyectos más rápido. En lugar de empezar propuestas desde cero, la app analiza la web de un cliente potencial, extrae información relevante, genera una propuesta comercial estructurada y crea un prototipo visual en minutos.

Para muchos freelancers, la velocidad es diferencial. He vendido sitios web por años y sé que, en ocasiones, se gana simplemente por ser más rápido que la competencia. Una herramienta que automatice la extracción de datos, estructure la propuesta y entregue una maqueta visual reduce el tiempo entre detectar una oportunidad y enviar la primera propuesta.

🧭 Flujo general de la solución

El sistema sigue este flujo básico:

  • Entrada: URL del posible cliente.
  • Lectura: extracción de texto desde la web (Gina Reader u otra herramienta de scraping/lectura).
  • Análisis: modelo de lenguaje que interpreta la información y genera una propuesta comercial.
  • Prototipo visual: captura visual (screenshot) de la página, que el modelo puede usar para análisis visual.
  • Salida: propuesta comercial estructurada y prototipo visual que el freelancer puede editar o enviar.

🔧 Primeros pasos: prototipar rápido en AI Studio

Para probar ideas rápido, empecé en Google AI Studio. Es ideal para prototipos porque permite iterar con prompts y modelos sin instalar todo localmente. El plan fue: crear un prototipo funcional, luego mover el proyecto a Antigravity para desarrollo y debugging más profundo.

Después de prototipar la idea, descargué el proyecto (zip) y lo trasladé a Antigravity. Abrí la carpeta descomprimida, revisé y levanté el proyecto. Con eso se arranca la aplicación localmente y se puede testear flujo completo contra sitios reales.

🕵️ Probar con un cliente real: detectar problemas reales

Probé con una clínica (una URL real) para ver si la app extraía la información correctamente. En el primer intento surgió un error: «has excedido tu cuota». Este tipo de fallos ocurren cuando trabajas con APIs externas y modelos: límites, claves inválidas o configuraciones que no contemplaste.

DevTools abierto con errores en rojo indicando 'You exceeded your current quota' y trazas relacionadas.

Primer aprendizaje: en prototipos reales siempre habrá errores. Lo importante es tener las herramientas para debuggear — abrir la consola del navegador (F12), revisar logs, y verificar si la causa es la cuota, el token o un endpoint mal llamado.

🔁 Cambio radical: cambiar el proveedor de IA

Para sortear la cuota decidí cambiar el proveedor de IA. Migré de Gemini a OpenRouter: obteniendo una nueva API key y configurando el proyecto para usar el nuevo proveedor. Cambiar el proveedor no es sólo intercambiar la API key; hay impactos funcionales que hay que revisar antes de hacerlo.

VS Code con archivo .env a la izquierda y un panel de agente a la derecha que muestra el análisis detallado sobre los impactos de cambiar de Gemini a OpenRouter

Al cambiar, la app evaluó el impacto automáticamente. El mayor problema detectado fue que la característica tools google search es exclusiva de la API directa de Gemini y OpenRouter no la soporta de forma nativa. Eso implica que, si dependes de una función propietaria de un proveedor, al migrar tendrás que replicar o reemplazar esa funcionalidad.

🧩 Solución práctica: Gina Reader como puente

Para seguir leyendo webs reales con OpenRouter, opté por implementar una solución combinada: usar Gina Reader para extraer el texto de la página y alimentar el modelo de OpenRouter con ese contenido. Gina Reader actúa como el scraper/lector y OpenRouter como el motor de razonamiento.

Ventajas de esta aproximación:

  • Independencia del proveedor: Gina Reader se encarga del scraping y el texto se puede enviar a cualquier modelo.
  • Flexibilidad: se puede cambiar el LLM sin perder la capacidad de leer páginas reales.
  • Rapidez: la separación de responsabilidades facilita debugging y pruebas A/B.
Pantalla 'Nuevo Proyecto' de la app mostrando el campo URL y el botón 'Analizar sitio automáticamente'

⚙️ Modelo económico: elegir versiones más baratas con contexto amplio

Para contener costos opté por probar «Grog 4.1 Fast», un modelo más barato con ventana de contexto amplia. La idea es que gran parte del trabajo requiere comprender bastante texto y, en muchos casos, no necesitas el modelo más caro. Buscar el equilibrio entre costo y capacidad es clave si piensas escalar la app.

Algunas consideraciones al elegir modelo:

  • Ventana de contexto: esencial si vas a enviar grandes cantidades de texto extraído de la web.
  • Coste por token: importante en flujos que generan muchas iteraciones o múltiples propuestas por día.
  • Soporte de herramientas: funciones como búsqueda web nativa o capacidades multimodales pueden ser exclusivas de ciertos proveedores.

✅ Primera prueba de fuego: análisis textual funciona

Tras cambiar y ajustar, el sistema pudo leer el texto real de la web y generar un análisis inicial. Ese fue un momento importante: la app ya era capaz de tomar una URL, extraer texto y producir un resumen/análisis. La presentación del análisis necesita pulirse, pero la lógica central funcionaba.

Interfaz mostrando 'Análisis del Proyecto' con un panel resaltado 'Problemas detectados' y lista de observaciones

Observación crítica: el análisis estaba basado únicamente en texto. No veía la página como lo haría un humano que la navega y observa diseño, jerarquía visual, imágenes o llamadas a la acción. Esto limita la calidad del diagnóstico y de las propuestas de valor.

👁️ Añadir análisis visual: por qué y cómo

Para enriquecer el análisis, decidí añadir una capa visual: tomar una captura de pantalla (screenshot) de la página y enviarla al modelo junto al texto. La combinación texto+imagen aporta contexto profundo:

  • Comprender la jerarquía visual y los elementos de la interfaz.
  • Detectar problemas de usabilidad o falta de llamadas a la acción.
  • Generar propuestas más relevantes, por ejemplo, sugerir cambios en la página de inicio basados en lo que se ve.

Desafío técnico: no puedes tomar un pantallazo directamente desde el navegador del usuario por restricciones de seguridad y CORS. Necesitas un servicio externo que genere la imagen a partir de la URL.

VS Code mostrando aiService.ts y texto contextual; captura clara del editor mientras se prepara la función de screenshots

La solución elegida fue usar Gina Screenshot AI, una API gratuita de la misma familia de herramientas que Gina Reader. El flujo quedó así:

  1. Gina Screenshot AI recibe la URL y devuelve la imagen (screenshot).
  2. Se muestra la imagen en la aplicación para que el usuario la vea.
  3. Se envía la imagen junto con el texto extraído al modelo para análisis multimodal.

🐞 Debugging en tiempo real: errores al enviar la imagen

Al integrar la captura visual surgieron errores. En un intento surgió un «bad request» y, tras probar otros modelos, un error 401. Lo que pasó normalmente es:

  • Intenté pasar la imagen directamente en la solicitud al modelo.
  • Algunas APIs esperan imágenes como multipart/form-data o URLs públicas en lugar de datos base64 embebidos.
  • En otros casos, el modelo o endpoint seleccionado no admite input multimodal (texto + imagen) o requiere un modelo específico.
Modal de error en la app indicando 'Error al generar el análisis' mientras se intentaba procesar la URL/screenshot.

El comportamiento observado: la app convirtió la imagen a base64 (lo que transforma la imagen en texto) y la pasó al modelo. Algunas plataformas aceptan base64; otras no. Además, algunos modelos nuevos acaban de salir y no están documentados aún, por eso el corrector automático o el IDE puede marcar que el nombre del modelo no existe, aunque sí lo haga en producción.

🔁 Experimentando con modelos: Gemini 2.5, 3.1 y más

Intenté cambiar los modelos para ver si alguno aceptaba la imagen sin errores. Pasé por Gemini 2.5 Flash y también probé una versión más nueva llamada 3.1 Flash Light Preview. A veces los modelos recién lanzados no aparecen en documentación ni en auto completion, pero sí existen en los endpoints reales.

Resultado: varios intentos arrojaron 401 o errores porque el endpoint no aceptaba la forma en que se enviaba la imagen. Eso me hizo comprender mejor dos cosas:

  • Documenta qué modelos soportan multimodal y cómo esperan la imagen (URL, multipart o base64).
  • Implementa una capa de compatibilidad donde tu app pueda transformar la imagen al formato esperado por cada proveedor.
OpenRouter mostrando modelos Gemini con el cursor sobre 'Google: Gemini 2.5 Flash Lite', columnas de precio y contexto visibles

🧠 Lección técnica: base64 vs multipart vs URL pública

Al integrar imágenes con LLMs o APIs multimodales encontrarás tres enfoques comunes:

  1. Base64 embebido: la imagen se convierte a una cadena base64 y se incluya en el body JSON. Es útil cuando no quieres subir archivos a un almacenamiento aparte. No todos los endpoints lo aceptan o pueden tener límites de tamaño.
  2. Multipart/form-data: la imagen se envía como archivo adjunto en una solicitud multipart. Es estándar para endpoints que manejan archivos y suele ser más eficiente con archivos grandes.
  3. URL pública: subes la imagen a un almacenamiento (S3, Cloud Storage) y envías la URL. Este método es robusto y evita problemas de tamaño en la request, pero requiere gestión de almacenamiento y permisos.

Para la app opté por mantener la opción de generar screenshots con Gina Screenshot AI y tener una capa que soporte convertir la imagen al formato que el modelo requiera. En la prueba la imagen se estaba enviando en base64, pero faltaba la lógica para mostrarla correctamente en la interfaz y/o para mandarla al modelo en el formato esperado.

Pantalla de Proposify con la caja 'Captura analizada' mostrando un placeholder 'Captura web' y la sección de problemas detectados debajo

📌 Recomendaciones prácticas para implementar esto en tu app

Si vas a construir una herramienta parecida, aquí tienes una checklist práctica y recomendaciones basadas en lo vivido:

  • Separa responsabilidades: usa un servicio para scraping (Gina Reader), otro para screenshots y un LLM para análisis. Así cambias una parte sin romper las demás.
  • Valida soporte multimodal: antes de depender de una característica (imagen+texto), verifica que el modelo y la API la soporten y cómo esperan el input.
  • Implementa fallback: si el modelo no soporta imágenes, procesa solo el texto y ofrece una opción para análisis visual manual o con otra ruta técnica.
  • Manejo de errores y logs: la consola del navegador y los logs del servidor son tus mejores amigos para identificar 401, 403, bad request y problemas de cuota.
  • Optimiza costos: prueba modelos «fast» o «light» con ventana de contexto suficiente antes de escalar a los más caros.
  • Transparencia con el usuario: muestra cuando la app no pudo procesar la imagen y ofrece alternativas (ej. subir screenshot manual).

🗂️ Ejemplo rápido: cómo pedir un screenshot a una API (curl)

Aquí tienes un ejemplo de cómo podrías pedir un screenshot a una API externa. Ajusta headers, URL y parámetros según la documentación de la API que uses.

curl -X POST "https://api.gina.ai/screenshot" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://ejemplo.com",
    "width": 1280,
    "height": 800,
    "fullPage": false
  }'

📥 Manejo de la imagen dentro de la app

Una vez recibida la imagen puedes:

  1. Mostrarla en la UI (renderizarla desde la URL o convertir base64 a data URI).
  2. Almacenar la imagen temporalmente y enviar la URL pública al modelo.
  3. Convertir a multipart/form-data y reenviarla si el modelo lo requiere.

Si usas base64 para mostrarla en el navegador, recuerda transformar la cadena en una data URI:

const dataUrl = `data:image/png;base64,${base64String}`;
// luego asignar a un  en la UI

🔒 Errores comunes y cómo resolverlos

  • 401 Unauthorized: revisa tu API key, permisos y si la ruta requiere un scope distinto.
  • Bad Request: valida el payload (tipo de dato, parámetros obligatorios, tamaño de imagen si se envía base64).
  • Límites de cuota: incorpora lógica para manejar rate limits, retries exponenciales y notificar al usuario.
  • Nombre del modelo no encontrado: modelos nuevos pueden no aparecer en autocompletado o docs públicas. Verifica con el proveedor.

💡 Ideas para mejorar la app a futuro

La versión básica ya da mucho valor, pero hay muchas formas de expandirla:

  • Templates de propuestas: plantillas personalizables por sector (salud, e-commerce, educación) que adapten lenguaje y métricas.
  • Análisis de competencia: usar la URL del cliente para buscar competidores y extraer benchmarks.
  • Integración con CRM: enviar propuestas generadas directamente a una pipeline de ventas.
  • Editor WYSIWYG: permitir editar propuestas y prototipos visuales antes de exportar PDF o enviar email.
  • Versionado y tracking: saber qué propuestas se enviaron, cuándo y con qué resultado.

🧪 ¿Qué aprendí en este build? Resumen de lecciones

Construir en público y en tiempo real enseña lecciones prácticas:

  • Prototipa rápido en herramientas como AI Studio, pero prepárate para trasladar el proyecto a entornos de desarrollo más controlados.
  • Cambiar proveedor de IA puede resolver problemas de cuota, pero requiere planear cómo reemplazar funcionalidades propias del proveedor original.
  • Separar el scraping de la inferencia (Gina Reader para texto, LLM para análisis) da flexibilidad y resiliencia.
  • Soporte multimodal (texto + imagen) mejora la calidad del análisis, pero introduce complejidad técnica en la transferencia y formato de imágenes.
  • Los errores 401/bad request son parte del proceso. Logs y consola son esenciales para resolverlos rápido.

🎯 Recursos y enlaces mencionados

Aquí dejo los enlaces relevantes y recursos comentados en el proceso. Pégalos en tu navegador o intégralos en tu proyecto.

Comunidad Skool (recursos y PrimeraApp.com para miembros):

https://www.skool.com/vibe-coding-crea-apps-con-ia-5930

Hosting de apps:

https://hostinger.com/rodrigo

Playlist con más videos sobre crear apps con IA:

https://www.youtube.com/playlist?list=PLBTuX25MUpdo9YuMzu-o9c80p1q40EBfI

📷 Screenshots del proceso (referencias visuales)

Las siguientes imágenes corresponden a momentos clave durante la construcción y debugging:

🎬 Video del proyecto

Si quieres ver el flujo corto y las decisiones en acción, está disponible una grabación condensada donde se muestra la construcción en tiempo real.

✍️ Cierre y próximos pasos

Este proyecto es un buen ejemplo de cómo combinar varias piezas: scraping, screenshots, modelos económicos y debugging iterativo. La idea central es entregar valor a freelancers mediante velocidad y calidad en propuestas comerciales. Si decides construir algo similar, comienza por separar responsabilidades, documenta las expectativas de cada API y agrega robustez frente a errores.

Si te interesa que continúe desarrollando y mostrando la evolución de esta app, o que publique una segunda parte con código y soluciones concretas al envío de imágenes y al manejo de multimodalidad, coméntalo y lo preparo.

Un abrazo y buen código.