automatiza.ia
Diagnóstico gratis
← Volver al blog
Stack 9 min · 2 de mayo, 2026

Le hice ingeniería inversa a la mejor web
de agencia de automatización del mundo.

Spoiler: el efecto de "partículas flotantes" que parece de Silicon Valley no usa GSAP, ni Three.js, ni Spline. Son 70 líneas de canvas vanilla y 5 keyframes CSS. Te muestro cómo replicarlo.

Hace unas semanas, mientras investigaba la estética de las agencias de automatización con IA más serias del mundo, di con n8nlab.io. Se ve increíble: tipografía custom, partículas violetas que respiran de fondo, iconos flotando con profundidad, glassmorphism sutil. Lo típico que hace pensar "esto lo hizo un equipo de 6 personas con un retainer de Apple".

Le hice ingeniería inversa al sitio (HTML, headers, bundle CSS, scripts) con un objetivo concreto: ¿qué stack y qué librerías necesito para tener algo así en mi agencia, siendo solo-founder con presupuesto cero?

La respuesta corta: mucho menos de lo que parece.

El stack real, verificado

Mirando los headers, los chunks que carga el bundle y los nombres de clase del CSS, lo que están usando es:

CapaTecnología
FrameworkNext.js 14 + Turbopack
HostingFirebase App Hosting tras Cloudflare CDN
UITailwind + shadcn/ui (paleta HSL custom violeta + coral)
Iconoslucide-react (gratis, mismo set que el del sitio que estás leyendo)
FuentesInter, Space Grotesk, Source Code Pro vía next/font
CRM / formsGoHighLevel detrás del botón "Get Free Audit"
BookingCal.com + TidyCal
ChatIntercom

Lo que no usan es lo más interesante: cero GSAP, cero Three.js, cero Spline, cero Lottie.El bundle no carga ninguna de esas librerías pesadas.

El truco del efecto "partículas flotantes"

Cuando ves el hero, parece animación 3D. La realidad: es un <canvas> fijo a pantalla completa con puntitos que rebotan + cinco keyframes CSS de Tailwind para los iconos que flotan arriba.

El componente esencial son ~70 líneas de JavaScript vanilla:

function ParticleCanvas() {
  const canvasRef = useRef(null);
  const rafRef = useRef(0);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    let w, h, dpr;
    const particles = [];

    const resize = () => {
      dpr = Math.min(window.devicePixelRatio || 1, 2);
      w = canvas.clientWidth; h = canvas.clientHeight;
      canvas.width = w * dpr; canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();

    for (let i = 0; i < 70; i++) {
      particles.push({
        x: Math.random() * w, y: Math.random() * h,
        vx: (Math.random() - 0.5) * 0.25,
        vy: (Math.random() - 0.5) * 0.25,
        r: Math.random() * 1.4 + 0.6,
        a: Math.random() * 0.5 + 0.2,
      });
    }

    const loop = () => {
      ctx.clearRect(0, 0, w, h);
      for (let i = 0; i < particles.length; i++) {
        const p = particles[i];
        p.x += p.vx; p.y += p.vy;
        if (p.x < 0 || p.x > w) p.vx *= -1;
        if (p.y < 0 || p.y > h) p.vy *= -1;
        for (let j = i + 1; j < particles.length; j++) {
          const q = particles[j];
          const d = Math.hypot(p.x - q.x, p.y - q.y);
          if (d < 130) {
            ctx.strokeStyle = `hsla(262, 83%, 70%, ${(1 - d/130) * 0.18})`;
            ctx.beginPath();
            ctx.moveTo(p.x, p.y); ctx.lineTo(q.x, q.y);
            ctx.stroke();
          }
        }
        ctx.fillStyle = `hsla(262, 83%, 75%, ${p.a})`;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();
      }
      rafRef.current = requestAnimationFrame(loop);
    };
    loop();

    return () => cancelAnimationFrame(rafRef.current);
  }, []);

  return <canvas ref={canvasRef} style={{ position:'absolute', inset:0 }} />;
}

Y para los iconos que "respiran" arriba del canvas, una sola animación CSS:

@keyframes float {
  0%, 100% { transform: translateY(0) rotate(var(--r, 0deg)); }
  50%      { transform: translateY(-14px) rotate(var(--r, 0deg)); }
}

Cada icono recibe un animation-delay diferente para que no respiren todos al mismo tiempo. Listo. Eso es todo el efecto.

Por qué te importa

La lección no es técnica, es de posicionamiento: el wow-factor de las landings que crees imposibles de replicar suele estar en la composición, no en el stack. Mucha gente que conozco está pagando $5,000 a una agencia que "hace animaciones 3D" cuando lo que necesitan es exactamente esto: 70 líneas de canvas + buen contraste de color + tipografía decente.

Si la única ventaja competitiva de tu landing es la animación, perdiste. Si la animación apoya un mensaje claro, ganaste — sin importar si lo hiciste con GSAP o con un canvas de 1 KB.

Lo que adopté para automatiza.ia

Esta misma web que estás leyendo usa el mismo enfoque:

Resultado: una landing que carga en menos de 100 KB de JavaScript, ranquea bien en Core Web Vitals, y se ve comparable a sitios de agencias internacionales que cobran 50× lo que yo voy a cobrar.

Si quieres copiar esto en tu negocio

Hay dos rutas. Ruta A: contrátame para que te lo monte en 14 días o menos, con tu copy y tu funnel. Ruta B: toma el código de arriba y ármalo tú mismo — está completo, no falta nada.

La Ruta B es legítima y la respaldo. Si eliges la A, agenda un diagnóstico gratis de 15 minutos:

Agendar diagnóstico gratis (15 min)


Si quieres ver el reporte forense completo (15 fuentes, headers HTTP, CSS bundle, alternativas de stack evaluadas), está disponible en el repo interno de la agencia. Pídemelo y te lo paso.

Próximamente
Cómo armar un bot de WhatsApp que reserve mesas en 14 días
Ver hoja de ruta