Cómo transmitir cambios de Postgres en vivo a un panel de Webflow Cloud con Supabase

Aprende a crear un panel de datos en tiempo real en Webflow Cloud usando Supabase Realtime.

Cómo transmitir cambios de Postgres en vivo a un panel de Webflow Cloud con Supabase

Colin Lateano
Evangelista de desarrolladores
Ver perfil del autor
Colin Lateano
Evangelista de desarrolladores
Ver perfil del autor
Índice de contenidos

Webflow Cloud te permite ejecutar una aplicación Next.js renderizada en el servidor junto a tu sitio de Webflow. Combínala con Supabase Realtime y obtendrás un panel de datos en vivo que se actualiza sin necesidad de recargar la página.

Con las Webflow Cloud Apps, puedes desplegar una aplicación Next.js junto a tu sitio de Webflow y obtener una página renderizada en el servidor que abre una conexión WebSocket con Supabase Realtime. Las nuevas filas de tu base de datos aparecerán en el panel en el momento en que se inserten. Sin recargas de página, sondeos ni ciclos de reconstrucción.

Esta guía explica cómo crear un panel de métricas en tiempo real en Webflow Cloud que se suscribe a los cambios en Supabase Postgres. El patrón se divide en dos capas: un componente de servidor que obtiene la instantánea inicial de los datos y un componente de cliente que mantiene la vista actualizada en tiempo real.

¿Qué necesitas para crear un panel en tiempo real en Webflow?

Necesitas tres cosas:

  • Una Webflow Cloud App
  • Un proyecto de Supabase con Realtime habilitado
  • Dos paquetes npm
Tabla de datos
Requisito Notas
Sitio de Webflow con un plan CMS o superior Webflow Cloud requiere un plan de sitio CMS o superior para montarse en un dominio personalizado
CLI de Webflow npm install -g @webflow/webflow-cli
Proyecto de Supabase El nivel gratuito funciona para el desarrollo
@supabase/supabase-js El cliente de JavaScript para uso tanto en servidor como en navegador
Node.js 20+ Requerido por el entorno de compilación de Webflow Cloud
Cuenta de GitHub Webflow Cloud puede desplegar desde un repositorio de GitHub conectado

Los seis elementos son necesarios antes de escribir cualquier código de componente. El nivel gratuito de Supabase admite Realtime de forma predeterminada, pero debes incluir explícitamente tu tabla en la supabase_realtime publicación (explicado en el paso 3).

Una vez que estén listos, puedes continuar con la compilación completa.

6 pasos para crear un panel de control en tiempo real con Supabase en Webflow Cloud

La construcción se divide en dos fases distintas. Los pasos 1 al 3 configuran la infraestructura: el esqueleto de la aplicación de Webflow Cloud, la conexión con Supabase y la publicación en tiempo real. Los pasos 4 y 5 crean los dos componentes de React que hacen que el panel funcione. El paso 6 realiza el despliegue.

La razón de tener dos componentes separados (Servidor y Cliente) es importante aquí.

Las suscripciones en tiempo real de Supabase son conexiones WebSocket mantenidas por el navegador. Un componente de servidor que se ejecuta en Cloudflare Workers no puede mantener una conexión WebSocket abierta. El componente de servidor gestiona la obtención inicial de datos mediante REST, pasa esa instantánea como propiedades (props) y el componente de cliente toma el relevo para transmitir las actualizaciones.

Con la tabla en la publicación y RLS configurado, la base de datos está lista. Los dos pasos siguientes crean los componentes que leerán de ella.

1. Crear el esqueleto de la aplicación de Webflow Cloud

Este comando se encarga de todo en una sola pasada: instala un proyecto inicial de Next.js, establece la ruta de montaje y vincula el proyecto a tu cuenta de Webflow. Solo tendrás que ejecutarlo una vez.

Instala la CLI de Webflow de forma global y luego ejecuta webflow cloud init para crear el esqueleto del proyecto:

npm install -g @webflow/webflow-cli
webflow cloud init

La CLI te pedirá que elijas un framework (selecciona Next.js), establezcas una ruta de montaje para la aplicación (por ejemplo, /dashboard), y te autentiques con tu cuenta de Webflow. La autenticación se realiza en línea durante init. No se requiere ningún comando de autenticación adicional en esta etapa.

Tras la autenticación, selecciona el sitio de Webflow al que deseas vincular la aplicación.

La CLI genera un esqueleto de proyecto con los siguientes archivos ya configurados:

your-app/
├── next.config.js          # basePath + assetPrefix set to your mount path
├── open-next.config.ts     # OpenNext adapter for Cloudflare Workers
├── cloudflare-env.d.ts     # TypeScript declarations for Cloudflare environment variables
├── wrangler.json           # Cloudflare Workers config (auto-generated, do not edit)
└── webflow.json            # Webflow project metadata

No edites wrangler.json directamente. Webflow Cloud lo regenera en cada despliegue basándose en tus webflow.json ajustes.

Resultado esperado: Una carpeta de proyecto Next.js completamente estructurada y vinculada a tu sitio de Webflow, con next.config.js conteniendo tu ruta de montaje tanto como basePath como assetPrefix.

2. Instala Supabase y configura tus variables de entorno

Con el esqueleto del proyecto listo, el siguiente paso es conectarlo a Supabase. Necesitarás la URL de tu proyecto y la clave anon del panel de control de Supabase. Ambas están disponibles en Configuración del proyecto → API.

Dentro del directorio del proyecto, instala el cliente de JavaScript de Supabase:

npm install @supabase/supabase-js

Luego abre el panel de control de tu proyecto en Supabase. Copia la URL de tu proyecto y la clave anon.

Añade ambas a un archivo .env.local en la raíz de tu proyecto:

NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

El prefijo NEXT_PUBLIC_ hace que estos valores estén disponibles tanto en los componentes de servidor como en los de cliente. La clave anon de Supabase es segura para exponerla en el navegador. El modelo de seguridad de Supabase se basa en la seguridad a nivel de fila (RLS), no en el secreto de la clave anon. Nunca utilices la clave de rol de servicio en código del lado del cliente.

Crea un archivo de cliente de Supabase compartido que ambos componentes importarán:

// lib/supabase.ts
import { createClient } from "@supabase/supabase-js";

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

Esta única instancia de cliente funciona tanto para la obtención inicial desde el servidor como para la suscripción en tiempo real desde el navegador. También deberás añadir estas variables de entorno a tu entorno de Webflow Cloud antes de realizar el despliegue (como se explica en el Paso 6).

Resultado esperado: @supabase/supabase-js instalado, .env.local completado con tus credenciales de Supabase y un archivo de cliente compartido en lib/supabase.ts.

3. Habilita Postgres Realtime en tu tabla de Supabase

Supabase Realtime no supervisa todas las tablas de forma predeterminada. Debes añadir tu tabla a la publicación supabase_realtime explícitamente.

Para hacerlo, en tu panel de control de Supabase, navega a Database → Publications. En supabase_realtime, activa la tabla a la que deseas suscribirte.

Alternativamente, puedes ejecutar este SQL en el editor SQL de Supabase:

-- Enable replication for the orders table
alter publication supabase_realtime add table orders;

-- Enable Row Level Security
alter table orders enable row level security;

-- Allow anonymous read access (adjust for your auth requirements)
create policy "Allow anonymous read"
  on orders
  for select
  to anon
  using (true);

Para esta guía, la tabla de ejemplo es orders con la siguiente estructura:

create table orders (
  id        serial primary key,
  customer  text not null,
  amount    numeric(10, 2) not null,
  status    text not null default 'pending',
  created_at timestamptz not null default now()
);

Una vez que se ejecute el SQL, la tabla orders formará parte de la publicación supabase_realtime y estará protegida por una política RLS. Cualquier cliente con una clave anon válida puede suscribirse ahora a eventos INSERT en esta tabla.

Captura de valores de filas antiguas con replica identity

Un ajuste importante: por defecto, los eventos UPDATE y DELETE solo devuelven el registro nuevo (o vacío) en la carga útil de Realtime.

Si tu panel necesita saber qué ha cambiado, establece replica identity en full:

alter table orders replica identity full;

Sin esto, las cargas útiles de UPDATE incluyen la nueva fila, pero no los valores anteriores. Para un panel de solo adición que muestra nuevos registros, este ajuste es opcional.

Resultado esperado: Tu tabla orders se añade a la publicación supabase_realtime y tiene una política RLS que permite el acceso de lectura.

4. Crea el componente de servidor para obtener los datos iniciales

El componente de servidor se ejecuta en Cloudflare Workers en el momento de la solicitud y obtiene los registros más recientes de Supabase a través de REST. Pasa esos datos como props al componente de cliente, que renderiza el panel.

Crea app/dashboard/page.tsx como un componente de servidor asíncrono. Obtiene los 50 pedidos más recientes en el momento de la solicitud y los pasa al componente de cliente como estado inicial:

// app/dashboard/page.tsx
import { supabase } from "@/lib/supabase";
import { DashboardClient } from "./dashboard-client";

export type Order = {
  id: number;
  customer: string;
  amount: number;
  status: string;
  created_at: string;
};

export default async function DashboardPage() {
  const { data: initialOrders, error } = await supabase
    .from("orders")
    .select("id, customer, amount, status, created_at")
    .order("created_at", { ascending: false })
    .limit(50);

  if (error) {
    console.error("Failed to fetch initial orders:", error.message);
  }

  return <DashboardClient initialOrders={initialOrders ?? []} />;
}

La matriz initialOrders alimenta el estado del componente de cliente. Cuando la página se carga, el usuario ve inmediatamente los últimos 50 pedidos, mientras la suscripción en tiempo real se abre en segundo plano a medida que el navegador se hidrata.

Este patrón evita el parpadeo del estado vacío que ocurre con la obtención de datos solo desde el cliente. El HTML que llega desde el servidor ya contiene los registros iniciales.

Resultado esperado: DashboardPage se renderiza en el lado del servidor con los 50 pedidos más recientes precargados como props para DashboardClient.

5. Crea el componente de cliente para actualizaciones en tiempo real

El componente de cliente mantiene los pedidos en el estado de React, abre un canal de Supabase Realtime al montarse y añade las nuevas filas al principio de la lista a medida que llegan.

Crea  con app/dashboard/dashboard-client.tsx en la parte superior. Este componente mantiene la lista de pedidos en el estado de React, abre el canal de Supabase al montarse y añade al principio las inserciones entrantes:"use client"

// app/dashboard/dashboard-client.tsx
"use client";

import { useEffect, useState } from "react";
import { supabase } from "@/lib/supabase";
import { Order } from "./page";

export function DashboardClient({
  initialOrders,
}: {
  initialOrders: Order[];
}) {
  const [orders, setOrders] = useState<Order[]>(initialOrders);

  useEffect(() => {
    const channel = supabase
      .channel("orders-live") // any string except 'realtime'
      .on(
        "postgres_changes",
        {
          event: "INSERT",
          schema: "public",
          table: "orders",
        },
        (payload) => {
          setOrders((prev) => [payload.new as Order, ...prev]);
        }
      )
      .subscribe();

    // Clean up the channel when the component unmounts
    return () => {
      supabase.removeChannel(channel);
    };
  }, []);

  return (
    <div className="dashboard">
      <h1>Live Orders</h1>
      <p>{orders.length} orders loaded — new orders appear automatically.</p>
      <table>
        <thead>
          <tr>
            <th>Customer</th>
            <th>Amount</th>
            <th>Status</th>
            <th>Time</th>
          </tr>
        </thead>
        <tbody>
          {orders.map((order) => (
            <tr key={order.id}>
              <td>{order.customer}</td>
              <td>${order.amount.toFixed(2)}</td>
              <td>{order.status}</td>
              <td>{new Date(order.created_at).toLocaleTimeString()}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

Hay un par de cosas a tener en cuenta en esta implementación. La directiva  en la parte superior le indica a Next.js que este componente se ejecuta en el navegador, algo necesario para "use client", useState y las conexiones WebSocket.useEffect

El nombre del canal  puede ser cualquier cadena de texto, pero "orders-live" está reservado por Supabase y hará que la suscripción falle. La función de limpieza en el "realtime" devuelve una llamada a useEffect. Si te saltas este paso, se producirán fugas de canal si el componente se vuelve a montar.supabase.removeChannel(channel)

La suscripción solo escucha eventos de  aquí. Para gestionar también las actualizaciones de pedidos existentes, añade un segundo oyente INSERT con .on() y fusiona la carga útil en el estado haciendo coincidir event: "UPDATE".id

Resultado esperado: El navegador abre una conexión WebSocket con Supabase al cargar la página. Cuando se inserta una nueva fila en la  , esta aparece en la parte superior de la tabla del panel sin necesidad de actualizar la página.orders table

6. Añade variables de entorno y despliega en Webflow Cloud

Antes de desplegar, añade tus credenciales de Supabase al entorno de Webflow Cloud.

En la configuración de tu sitio de Webflow, navega hasta Webflow Cloud, abre el entorno de tu proyecto y añade las siguientes variables en Variables de entorno:

NEXT_PUBLIC_SUPABASE_URL      = https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY = your-anon-key-here

A continuación, autentícate y despliega desde la CLI:

webflow auth login
webflow cloud deploy

webflow auth login abre una ventana del navegador para autenticar tu cuenta de Webflow. Tras conceder el acceso, ejecuta webflow cloud deploy para enviar tu proyecto. También puedes enviarlo a tu rama de GitHub conectada y Webflow Cloud iniciará el despliegue automáticamente.

Los despliegues suelen completarse en menos de dos minutos. Supervisa el estado de la compilación y los registros en el panel de Webflow Cloud, dentro del historial de despliegue de tu entorno.

Resultado esperado: Tu panel está activo en  . Los nuevos pedidos insertados en Supabase aparecen en el navegador en tiempo real sin necesidad de actualizar la página.your-site.webflow.io/dashboard

¿Por qué dejan de funcionar las actualizaciones en tiempo real de Supabase en Webflow Cloud?

La mayoría de los fallos en tiempo real se deben a una de estas cuatro causas: la tabla no se añadió a la publicación Realtime, el nombre del canal entra en conflicto con una cadena reservada, la suscripción se creó en un componente de servidor o falta la función de limpieza y se están produciendo fugas de canales.

Cada causa tiene un síntoma distinto, lo que facilita su aislamiento. Las siguientes secciones las abordan en orden de frecuencia.

Las actualizaciones nunca llegan al navegador

Causa: La tabla no está en la publicación  . Este es el error más común en el primer despliegue.supabase_realtime

Solución: Ejecuta  en el editor SQL de Supabase y confirma que aparece tu tabla. Si no es así, ejecuta select * from pg_publication_tables where pubname = 'supabase_realtime';.alter publication supabase_realtime add table your_table;

La suscripción se abre, pero no se activa ningún evento

Causa: El nombre del canal está configurado como "realtime". Supabase reserva esta cadena. Los canales que la utilicen no recibirán eventos.

Solución: Cambia el nombre del canal por cualquier otro: "orders-live", "dashboard-feed" o cualquier cadena descriptiva.

Error de consola: "supabase is not defined" en un componente de servidor

Causa: Se escribió una suscripción en tiempo real en un componente de servidor o en un archivo sin "use client" en la parte superior. Las conexiones WebSocket no pueden mantenerse abiertas en el servidor.

Solución: Mueve la llamada a .channel() y el hook useEffect a un archivo que tenga "use client" como primera línea. El componente de servidor solo debe obtener datos; el componente de cliente debe suscribirse.

La suscripción se activa en la primera carga, pero se detiene tras la navegación

Causa: Falta la función de limpieza useEffect. Cuando el componente se desmonta (al navegar), el canal antiguo no se elimina. Cuando el componente se vuelve a montar, se crea un canal duplicado y uno o ambos dejan de recibir eventos.

Solución: Devuelve siempre () => { supabase.removeChannel(channel); } desde el useEffect. Verifica en el panel de control de Supabase Realtime (Realtime → Inspector) que solo aparezca una suscripción de canal para tu tabla.

Los eventos DELETE se activan pero no incluyen datos

Causa: replica identity está configurado por defecto en (default), lo que no captura los valores de las filas antiguas para las eliminaciones. Además, Supabase Realtime no admite filtros a nivel de columna en eventos DELETE. No puedes filtrar event: "DELETE" por el valor de una columna específica.

Solución: Ejecuta alter table your_table replica identity full; para recibir el registro antiguo en los eventos DELETE. Ten en cuenta que con RLS habilitado (como se configura en esta guía), el registro antiguo solo incluirá la(s) clave(s) primaria(s), no la fila completa. Si tu panel solo necesita saber que ocurrió una eliminación y no qué se eliminó, la identidad por defecto es suficiente.

Crea experiencias en vivo con Supabase y Webflow Cloud

Esta guía cubrió un panel de solo lectura que muestra nuevos pedidos en tiempo real. El mismo patrón se aplica a cualquier dato que cambie con frecuencia: colas de tickets de soporte, feeds de envíos de formularios, registros de actividad de usuarios y rastreadores de inventario.

Explora Webflow + Supabase para la configuración de autenticación, sincronización de CMS y opciones de conexión sin código, además de cómo añadir autenticación de usuario para controlar quién puede ver el panel.

Preguntas frecuentes

¿Funciona Supabase Realtime en el plan gratuito de Webflow Cloud?

El plan gratuito de Supabase incluye Realtime. Webflow Cloud requiere un plan de sitio CMS o superior. La conexión WebSocket se ejecuta en el navegador del usuario, no en el Cloudflare Worker, por lo que no consume tu cuota de computación en la nube.

¿Puedo suscribirme a varias tablas a la vez?

Sí. Encadena varias llamadas a .on() en el mismo canal o crea canales separados para cada tabla. Un solo canal puede escuchar diferentes tablas, esquemas y tipos de eventos simultáneamente. Los canales separados facilitan la limpieza de las suscripciones de forma independiente.

¿Por qué no puedo ejecutar la suscripción de Supabase Realtime en un componente de servidor?

Los Server Components se ejecutan en Cloudflare Workers y devuelven HTML. No pueden mantener conexiones persistentes. Los WebSockets requieren una conexión de navegador de larga duración. Cualquier .channel() llamada debe realizarse dentro de un Client Component con "use client" en la parte superior.

¿Qué sucede con las actualizaciones en tiempo real cuando el usuario navega fuera y regresa?

La useEffect limpieza desmonta el canal al navegar. Cuando el usuario regresa, el Server Component vuelve a obtener la última instantánea y la pasa al Client Component, que reabre la suscripción en tiempo real. Cualquier fila insertada durante el periodo de ausencia se incluye en la nueva obtención del servidor.

¿Es seguro exponer la clave anon de Supabase en el navegador?

La clave anon está diseñada para ser pública. El modelo de seguridad de Supabase utiliza políticas de Row Level Security (RLS) para controlar el acceso a los datos. La clave anon por sí sola no otorga acceso ilimitado. Nunca expongas la clave service_role en código del lado del cliente ni le añadas el prefijo NEXT_PUBLIC_.


Última actualización
May 9, 2026
Categoría

Artículos relacionados

Cómo conectar un formulario de Webflow a Mailchimp sin perder suscriptores ni arruinar tu diseño
Cómo conectar un formulario de Webflow a Mailchimp sin perder suscriptores ni arruinar tu diseño

Cómo conectar un formulario de Webflow a Mailchimp sin perder suscriptores ni arruinar tu diseño

Cómo conectar un formulario de Webflow a Mailchimp sin perder suscriptores ni arruinar tu diseño

Desarrollo
Por
Colin Lateano
,
,
Leer artículo
Cómo abrir un modal de Typeform al hacer clic en un botón en Webflow sin redirigir a los usuarios
Cómo abrir un modal de Typeform al hacer clic en un botón en Webflow sin redirigir a los usuarios

Cómo abrir un modal de Typeform al hacer clic en un botón en Webflow sin redirigir a los usuarios

Cómo abrir un modal de Typeform al hacer clic en un botón en Webflow sin redirigir a los usuarios

Desarrollo
Por
Colin Lateano
,
,
Leer artículo
Cómo usar la API de CMS de Webflow para leer, escribir y publicar contenido mediante programación
Cómo usar la API de CMS de Webflow para leer, escribir y publicar contenido mediante programación

Cómo usar la API de CMS de Webflow para leer, escribir y publicar contenido mediante programación

Cómo usar la API de CMS de Webflow para leer, escribir y publicar contenido mediante programación

Desarrollo
Por
Colin Lateano
,
,
Leer artículo
Cómo insertar un widget de Booking.com en Webflow sin romper la versión móvil
Cómo insertar un widget de Booking.com en Webflow sin romper la versión móvil

Cómo insertar un widget de Booking.com en Webflow sin romper la versión móvil

Cómo insertar un widget de Booking.com en Webflow sin romper la versión móvil

Desarrollo
Por
Colin Lateano
,
,
Leer artículo

verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logoreddit logothe new york times logoideo logoupwork logodiscord logo
verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logoreddit logothe new york times logoideo logoupwork logodiscord logo

Empieza gratis

Prueba Webflow todo el tiempo que quieras con nuestro plan Starter gratuito. Compra un plan de sitio de pago para publicar, alojar y desbloquear funciones adicionales.

Empieza, es gratis
Ver demostración

Prueba Webflow todo el tiempo que quieras con nuestro plan Starter gratuito. Compra un plan de sitio de pago para publicar, alojar y desbloquear funciones adicionales.