Construir para el flujo real, no para el diagrama

March 8, 2026
6 min read
Table of Contents

Hace poco estuve trabajando en una web para JG Andamios, un negocio en Cali enfocado en compra y venta de andamios certificados, nuevos y usados.

No era una startup. No era una plataforma. No había que inventar un dashboard ni una app.

Era una web para un negocio real, con necesidades bastante concretas:

  • explicar qué venden
  • mostrar confianza
  • aparecer en búsquedas locales
  • responder preguntas comunes
  • recibir leads
  • llevar rápido a una conversación

Justo por eso me pareció interesante. Los proyectos pequeños tienen menos espacio para esconder malas decisiones detrás de arquitectura sofisticada. Si algo no ayuda a que el usuario entienda, confíe o contacte, probablemente sobra.

La idea que me quedó fue esta:

A veces construimos software pensando en el flujo ideal que dibujamos nosotros, no en el flujo real donde la gente ya trabaja.

El Flujo Real No Era Un Formulario

En papel, una web de negocio local puede terminar en un formulario clásico:

  • nombre
  • correo
  • teléfono
  • mensaje
  • botón de enviar

Eso se ve limpio. Es fácil de implementar. Y para muchos casos funciona.

Pero en este proyecto había algo raro con dejar el formulario como destino principal. La persona que está buscando andamios no necesariamente quiere hacer una “solicitud” formal. Probablemente quiere preguntar algo mucho más inmediato:

  • si hay disponibilidad
  • cuánto cuesta cierto equipo
  • si reciben andamios usados
  • si el producto es certificado
  • si hacen entrega en Cali o alrededores
  • si puede mandar una foto de lo que necesita vender o comprar

Ese flujo no empieza tan bien con un inbox. Empieza mejor con una conversación.

Y en Colombia, para este tipo de negocio, esa conversación casi siempre vive en WhatsApp.

La Web Como Punto De Entrada

La decisión no fue “pongamos un botón de WhatsApp porque convierte”.

La decisión fue más básica: la web no tenía que reemplazar el canal donde ya pasaba la negociación. Tenía que preparar el contexto y mandar a la persona al canal correcto.

Por eso el sitio terminó teniendo varias entradas al mismo flujo:

  • CTA principal en el hero: cotizar por WhatsApp.
  • Botón de llamada como segunda opción.
  • Barra fija en móvil con WhatsApp y llamada.
  • CTAs dentro de los artículos del blog.
  • Formulario para quien sí prefiere dejar datos.

Lo interesante es que el formulario tampoco quedó como una isla separada. Al enviarlo, construye un mensaje con los datos de la persona y abre WhatsApp:

ContactForm.astro
const mensaje = `Hola, soy ${nombre}. Necesito información sobre: ${servicio}. Mi teléfono es ${telefono}.`
const whatsappUrl = `https://wa.me/573215406137?text=${encodeURIComponent(mensaje)}`
 
window.open(whatsappUrl, '_blank')

Después intenta enviar el payload por Web3Forms como respaldo.

Me gusta esa solución porque no pelea contra el hábito del usuario. Si alguien quiere llenar un formulario, puede hacerlo. Pero el sistema sigue llevando la interacción hacia el lugar donde el negocio realmente responde.

Un Lead No Es Solo Un Click

Otra cosa que me pareció útil fue separar los tipos de contacto.

No todos los leads tienen la misma intención. Alguien que hace click en “Llamar” está en un modo distinto a alguien que abre WhatsApp desde un artículo del blog. Y alguien que llena un formulario con “Quiero vender mi equipo” no está pidiendo lo mismo que quien busca comprar andamios nuevos.

El sitio no necesitaba un CRM completo para eso. Pero sí tenía sentido medir los puntos básicos:

Layout.astro
window.gtag('event', 'generate_lead', {
  lead_source: type,
  currency: 'COP',
  value: 1,
})

No es una arquitectura compleja. Es apenas suficiente para responder preguntas concretas:

  • ¿la gente prefiere llamar o escribir?
  • ¿los artículos generan contactos?
  • ¿el formulario se usa o solo estorba?
  • ¿qué intención trae el usuario?

Esa es una diferencia que me parece importante: instrumentar no para llenar dashboards, sino para aprender si el flujo que diseñaste corresponde al comportamiento real.

SEO Local Como Modelado Del Contexto

El proyecto también necesitaba contenido.

No contenido por tener blog, sino porque las preguntas del negocio ya existían:

  • “cuánto cuesta comprar andamios en Cali”
  • “andamios certificados vs tubulares”
  • “normativa de seguridad para andamios en Colombia”
  • “compran andamios usados en Cali”
  • “venta de andamios nuevos y usados”

Ahí Astro Content Collections encajó bien. Cada artículo vive como Markdown con frontmatter validado. Si falta un título, una fecha está mal o un campo no cumple el schema, el build falla antes de publicar.

src/content/config.ts
const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.coerce.date(),
    author: z.string().default('JG Andamios'),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
})

Esto daba suficiente estructura sin meter un CMS, usuarios, paneles o una base de datos que el proyecto no necesitaba.

También hubo trabajo invisible pero importante: lang="es-CO", og:locale, formato de fechas en español de Colombia, schema LocalBusiness, schema BlogPosting, breadcrumbs y ubicación real en Cali.

No lo veo como “hacer SEO” en el sentido barato. Lo veo como describir bien el sistema para humanos y para máquinas:

  • qué es el negocio
  • dónde opera
  • qué vende
  • qué preguntas responde
  • cómo puede contactarlo alguien

La Arquitectura Tenía Que Ser Proporcional

El stack terminó siendo bastante simple: Astro, Tailwind, contenido estático, imágenes optimizadas y un poco de JavaScript donde sí hacía falta.

Eso fue deliberado.

Una web así no necesita mandar un bundle enorme para mostrar un teléfono, una dirección y una galería. Tampoco necesita SSR si el contenido cambia poco. Necesita cargar rápido, especialmente en móvil, y dejar clara la siguiente acción.

astro.config.mjs
import { defineConfig } from 'astro/config'
import tailwindcss from '@tailwindcss/vite'
 
export default defineConfig({
  vite: {
    plugins: [tailwindcss()],
  },
})

La parte técnica sigue la misma idea del producto: usar lo suficiente.

No cero ingeniería. No sobreingeniería. Lo suficiente para que el sistema sea mantenible, rápido y útil.

Lo Que Me Interesa De Este Proyecto

No creo que la conclusión sea “todas las webs en LATAM deben ser WhatsApp-first”.

Eso sería convertir una observación real en una regla floja.

La conclusión que sí me interesa es más amplia: antes de construir una interfaz nueva, hay que mirar dónde vive el trabajo hoy.

Esto aplica a proyectos de datos, automatizaciones y sistemas con IA.

Antes de hacer un dashboard, vale preguntar si la decisión realmente se toma en un dashboard.

Antes de hacer un agente, vale entender qué pasos hace hoy la persona, qué información necesita, qué parte requiere criterio y en qué canal ocurre el trabajo.

Antes de reemplazar un proceso completo, vale revisar si el mejor sistema es uno que se conecte con el proceso existente.

Muchas soluciones fallan no porque la tecnología sea mala, sino porque intentan imponer una interfaz que no tiene lugar en la vida real del usuario.

Cierre

Este fue un proyecto pequeño, pero me dejó una lección que quiero seguir aplicando:

el software útil no siempre crea un hábito nuevo.

A veces entiende uno que ya existe y se conecta bien con él.

En este caso, la web no era el centro del negocio. Era un punto de entrada: rápido, local, encontrable y conectado a WhatsApp.

Eso puede sonar menos ambicioso que construir una plataforma completa, pero para mí es una señal de buen criterio: escribir solo el software que el problema realmente está pidiendo.