Rooming Viajes y Turismo

Cliente · 2026

Sitio de reservas de una agencia tucumana, con checkout de Mercado Pago y portal B2B.


Estado
En producción · rooming.com.ar
Rol
Diseño, desarrollo y operación, solo
Período
Mar 2026 – hoy
deploys a producción
109
Vercel, de marzo a octubre de 2026
rutas prerenderizadas
28
de 8 a 28 con SSG
peso de una galería
−79 %
2.426 → 494 KB, medido en laboratorio
entre el navegador y mi SaaS
BFF
4 rutas; la clave nunca llega al navegador

El proyecto en 30 segundos

  1. El problema

    Una agencia de viajes tucumana necesitaba vender sus viajes grupales en su propio sitio, con cobro online y un canal para agencias revendedoras.

  2. Lo que armé

    Un sitio sin base de datos propia: catálogo, precios y cobro salen de mi SaaS, basecode.com.ar, que la agencia usa como panel. El navegador nunca decide cuánto se cobra y los datos de la tarjeta nunca pasan por mi servidor.

  3. En qué quedó

    En producción desde marzo de 2026, con 109 deploys y la agencia editando sus viajes desde el panel. El checkout todavía no tuvo ventas.

Qué pasa cuando alguien paga

  1. Navegador
    Pide

    Elige el viaje y los pasajeros, y pide una cotización. La tarjeta se carga en los campos seguros de Mercado Pago, que devuelven un token.

  2. Sitio (Next.js)
    Reenvía

    Pasa la cotización y el token al backend con su clave, que nunca llega al navegador, junto con la IP del visitante para los topes.

  3. basecode.com.ar
    Firma y cobra

    Calcula el precio, lo firma y, al pagar, cobra el monto firmado.

  4. Mercado Pago
    Aprueba

    Aprueba el pago.


Resultado: El comprador ve su reserva confirmada, y los datos de la tarjeta nunca pasaron por el sitio.

Sobre el proyecto

Rooming Viajes y Turismo, mi primer cliente, necesitaba vender sus viajes grupales en su propio sitio. Lo construí en marzo de 2026 y lo mantengo desde entonces: manejo el hosting, el dominio y cada deploy, y propuse la mayoría de las funcionalidades. El sitio no tiene base propia: el catálogo, los precios y el cobro salen de mi SaaS, basecode.com.ar, que la agencia usa como panel. El centro es el camino de la plata: el navegador nunca decide cuánto se cobra y los datos de la tarjeta nunca pasan por mi servidor. Alrededor suma fichas prerenderizadas con SEO técnico, excursiones que cierran por WhatsApp, un portal B2B para agencias revendedoras y medición detrás de un aviso de consentimiento.

Para tener en cuenta

El checkout está en producción y todavía no tuvo ventas. La medición con GA4 y Meta está implementada y falta activarla con los IDs de producción. Todavía no tiene tests automatizados ni CI: el build de Vercel es el único control, y el checkout lo probé a mano. El componente del checkout (unas 700 líneas) es la deuda más grande, y los pedidos del navegador todavía no tienen timeout.

Lo que construí, por área

A · Frontend

Ingeniería de UI/UX y rendimiento

Un sistema de diseño liviano, accesible y medido sobre el build.

−79 %peso de una galería (2.426 → 494 KB), medido en laboratorio
  • Sistema de diseño con Tailwind 4 y tokens propios, sin librería de componentes.
  • El logo del navbar, el swipe de la galería y los testimonios se animan sin pasar por React: variable CSS, transform por ref y medición solo en pantalla.
  • Selector de tipo de documento de Mercado Pago que se maneja con teclado; formularios que anuncian su estado con aria-live; aviso de cookies con rol y foco.
  • La validación (zod) se descarga recién al abrir el panel de reserva.
  • Cloudinary con un tamaño para cada uso: la fuente de íconos pasó de 323.740 a 8.052 bytes.
Ver detalle técnico
  • De 8 a 28 rutas prerenderizadas, con sitemap, URL canónica, datos estructurados y vista previa propia al compartir por WhatsApp.
  • Las cifras de peso están medidas sobre el output del build, en laboratorio; no hay todavía métricas de campo.
  • Tailwind 4
  • React 19
  • Server Components
  • Zod
  • Cloudinary
B · Backend

Arquitectura, BFF e integraciones

El sitio no tiene base de datos: es un cliente más de mi SaaS.

4 rutasBFF entre el navegador y el backend; la clave nunca sale del servidor
  • Catálogo, precio y cobro viven en basecode.com.ar; el sitio solo los presenta.
  • BFF en Next.js: las rutas del sitio guardan la clave, le pasan la IP del visitante al backend y devuelven errores genéricos.
  • Cuando la agencia edita un viaje, el SaaS avisa y el sitio purga la caché al instante (expire: 0). Si el aviso se pierde, vence solo a los 60 segundos.
  • BackendUnavailableError distingue «catálogo vacío» de «no pude preguntar»: sirve la última versión buena, y un deploy con el backend caído falla en vez de publicar un sitio vacío.
  • Pago seguro: el precio lo firma el backend y la tarjeta se tokeniza en los campos seguros de Mercado Pago.
Ver detalle técnico
  • La cotización se invalida si cambian los pasajeros o los extras.
  • Se sacaron los registros de la respuesta de Mercado Pago y las notas internas de diseño que se servían en el HTML de /mayoristas.
  • Next.js 16
  • BFF
  • Mercado Pago
  • Vercel
  • basecode.com.ar
C · Producto

Soluciones de negocio (B2C y B2B)

Cada pantalla resuelve un problema de la agencia, no solo de diseño.

17motivos de rechazo de Mercado Pago traducidos a qué puede hacer el comprador
  • Portal B2B /mayoristas: tarifario interactivo por mes y base de habitación con tarifa, gasto administrativo, comisión y total; cierra por WhatsApp con la selección armada. Queda fuera de los buscadores.
  • Promotores por link (?ref=): gana el último link y se recuerda 30 días solo si el visitante aceptó las cookies.
  • GA4 y Meta Pixel no reciben ningún pedido hasta que el visitante acepta; el embudo no manda datos personales. La medición está implementada y falta activarla con los IDs de producción.
  • La pantalla de error ofrece contacto por WhatsApp; las excursiones y mejoras pagas se eligen igual en la ficha y en el panel de reserva.
  • B2B
  • GA4
  • Meta Pixel
  • WhatsApp

Decisiones y qué resignan

Consistencia

Una sola fuente de verdad

Elegí
El sitio es un cliente más del SaaS.

Resigné
Independencia: si el backend cae, el sitio lo siente.
Por qué

El sitio no tiene base: es un cliente más del SaaS. El catálogo, el precio y el cobro viven en un solo lugar. Lo que se resigna es independencia: si el backend cae, el sitio lo siente, y por eso existe la decisión siguiente.

Disponibilidad

Ante una caída, disponibilidad

Elegí
Servir la última versión buena del catálogo.

Resigné
Que el build falle a propósito antes que publicar un sitio vacío.
Por qué

Un catálogo vacío y un backend caído son errores distintos. Si el backend no responde, se sirve la última versión buena en vez de una página vacía, y el build falla para que no se publique un sitio roto.

Consistencia

Para la plata, consistencia

Elegí
Purgar la caché al instante (expire: 0).

Resigné
Más pedidos al backend después de cada edición.
Por qué

La caché del catálogo se purga al instante cuando cambia un precio, para que nadie vea uno viejo. Un TTL de 60 segundos cubre el caso de un aviso perdido. El costo: más pedidos al backend después de cada edición.

Seguridad

Un BFF entre el navegador y el backend

Elegí
Cuatro rutas del sitio que guardan la clave.

Resigné
Una pieza más para mantener.
Por qué

El navegador nunca habla directo con el SaaS: cuatro rutas del sitio guardan la clave, devuelven errores genéricos y le pasan la IP del visitante al backend para los topes. Es una pieza más para mantener, a cambio de que la clave no quede en el bundle.

Lo que sigue

En este orden y por esta razón: primero poder cambiar sin miedo, después cerrar deudas, recién entonces medir.

  1. Ahora

    Hoy el build de Vercel es el único control: sin red de seguridad no se puede cambiar con confianza.


    • CI con lint, tipos y build en cada push, antes de cada deploy.
    • Tests de la lógica del checkout y un recorrido de punta a punta con tarjetas de prueba.
  2. Después

    Cierra las deudas que ya declaro en «Para tener en cuenta».


    • Que el sitio respete los errores del backend (400 y 429 en vez de un 500) y que cada pedido tenga timeout.
    • Partir el componente del checkout (unas 700 líneas).
  3. Más adelante

    Con la base estable tiene sentido medir; hoy no hay cifras de campo y no las invento.


    • Medir rooming.com.ar con Lighthouse y dejar los números en el repo.
    • Métricas de campo (Core Web Vitals) y activar GA4 y Meta con los IDs de producción.

Cómo usé IA

Lo trabajé con Claude Code. Antes de cada cambio grande auditamos el sitio: cada hallazgo con su estado, y uno retirado cuando no se sostuvo al revisarlo. Cada arreglo fue un commit chico con la causa y cómo se verificó. Cuando una corrección del agente empeoró el logo, seguí el problema hasta la causa (el optimizador de imágenes) y quedó escrita como regla para el próximo cambio.