🌐 Detecting your location…

Como construir um aplicativo em tempo real com Next.js e Supabase em 2026

⏱️6 min read  ·  1,198 words

Supabase fornece um banco de dados PostgreSQL, autenticação e assinaturas em tempo real como um backend gerenciado — combinando perfeitamente comPróximo.js para criar aplicativos full-stack em tempo real rapidamente. Este guia cria um aplicativo em tempo real, desde o banco de dados até a implantação.

Por que Next.js + Supabase?

  • Backend completo sem construir um: Banco de dados, autenticação, armazenamento e tempo real prontos para uso
  • PostgreSQL real: Não é um banco de dados proprietário — SQL padrão que você pode consultar diretamente
  • Assinaturas em tempo real: Ouça as alterações do banco de dados ao vivo com o mínimo de código
  • Autenticação integrada: Email, OAuth, links mágicos — nenhuma infraestrutura de autenticação para construir
  • Código aberto: Auto-hospedável, evitando a dependência de fornecedores

Configuração

npx create-next-app@latest my-app
cd my-app
npm install @supabase/supabase-js @supabase/ssr
# Create a project at supabase.com, then add to .env.local
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

Configuração do cliente Supabase

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

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

Crie uma Tabela (Editor SQL no Supabase)

-- Create a messages table
create table messages (
  id uuid default gen_random_uuid() primary key,
  content text not null,
  user_id uuid references auth.users,
  created_at timestamptz default now()
);

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

-- Policy: anyone can read messages
create policy "Messages are viewable by everyone"
  on messages for select using (true);

-- Policy: authenticated users can insert their own messages
create policy "Users can insert their own messages"
  on messages for insert
  with check (auth.uid() = user_id);

Assinaturas em tempo real

// components/Chat.jsx
'use client';
import { useState, useEffect } from 'react';
import { supabase } from '@/lib/supabase';

export default function Chat() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    // Load existing messages
    supabase.from('messages').select('*').order('created_at')
      .then(({ data }) => setMessages(data || []));

    // Subscribe to new messages in real time
    const channel = supabase
      .channel('messages')
      .on('postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'messages' },
        (payload) => {
          setMessages(prev => [...prev, payload.new]);
        }
      )
      .subscribe();

    // Cleanup subscription
    return () => { supabase.removeChannel(channel); };
  }, []);

  const sendMessage = async (content) => {
    const { data: { user } } = await supabase.auth.getUser();
    await supabase.from('messages').insert({ content, user_id: user.id });
  };

  return (
    <div>
      {messages.map(m => <div key={m.id}>{m.content}</div>)}
    </div>
  );
}

Autenticação

// Sign up
async function signUp(email, password) {
  const { data, error } = await supabase.auth.signUp({ email, password });
  if (error) throw error;
  return data;
}

// Sign in
async function signIn(email, password) {
  const { data, error } = await supabase.auth.signInWithPassword({ email, password });
  if (error) throw error;
  return data;
}

// OAuth (Google, GitHub, etc.)
async function signInWithGitHub() {
  await supabase.auth.signInWithOAuth({ provider: 'github' });
}

// Get current user
const { data: { user } } = await supabase.auth.getUser();

// Sign out
await supabase.auth.signOut();

Componentes do servidor e busca de dados

// app/page.jsx - Server Component fetching data
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export default async function Page() {
  const cookieStore = cookies();
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    { cookies: { get: (name) => cookieStore.get(name)?.value } }
  );

  const { data: messages } = await supabase
    .from('messages')
    .select('*')
    .order('created_at', { ascending: false })
    .limit(20);

  return <MessageList initialMessages={messages} />;
}

Segurança em nível de linha: a chave para dados seguros

Supabase usa PostgreSQL Row Level Security (RLS) para controlar o acesso aos dados. Como o cliente se conecta diretamente à chave anônima, as políticas RLS são o que mantém os dados seguros – elas definem quem pode ler/escrever o quê. Sempre habilite o RLS em suas tabelas e escreva políticas. Sem RLS, seus dados ficam expostos. O RLS não é opcional para produção — é a base de segurança do modelo de cliente direto.

Implantação

# Deploy to Vercel (seamless with Next.js)
# 1. Push to GitHub
# 2. Import the repo in Vercel
# 3. Add environment variables (NEXT_PUBLIC_SUPABASE_URL, ANON_KEY)
# 4. Deploy

# Supabase is already hosted - no backend deployment needed.
# Your Next.js frontend on Vercel + Supabase backend = full-stack app live.

Perguntas Frequentes

P: Supabase é uma boa alternativa para construir meu próprio backend?
R: Sim, para muitos aplicativos — ele fornece um banco de dados PostgreSQL real, autenticação, armazenamento e tempo real sem construir infraestrutura de back-end. Você obtém SQL padrão (não um banco de dados proprietário), então não fica preso. É excelente para desenvolvimento rápido de pilha completa e MVPs.

P: Como funciona o tempo real no Supabase?
R: Supabase escuta as alterações do PostgreSQL e as envia para clientes inscritos por meio de WebSockets. Você assina eventos INSERT/UPDATE/DELETE em uma tabela e seu retorno de chamada é acionado quando os dados são alterados. O código mínimo oferece atualizações ao vivo – ótimo para bate-papo, notificações e recursos colaborativos.

P: É seguro usar o Supabase diretamente do cliente?
R: Sim, SE você usar a segurança em nível de linha (RLS). Como o cliente se conecta à chave anônima, as políticas de RLS controlam o que cada usuário pode ler/gravar. Sempre habilite o RLS e escreva políticas — é a base da segurança. Sem RLS, seus dados ficam expostos. Nunca pule isso na produção.

P: Supabase ou Firebase?
R: Supabase usa PostgreSQL (SQL padrão, relacional, sem lock-in) e é de código aberto/auto-hospedável. O Firebase usa um banco de dados NoSQL proprietário. Escolha Supabase se preferir SQL, dados relacionais e evitar aprisionamento; Firebase por seu ecossistema maduro e se o NoSQL se ajusta aos seus dados. Ambos oferecem autenticação e tempo real.

P: Posso auto-hospedar o Supabase?
R: Sim — Supabase é de código aberto e pode ser auto-hospedado, evitando a dependência de um fornecedor. A maioria começa com a nuvem gerenciada (nível gratuito generoso) e pode se auto-hospedar posteriormente, se necessário. A opção de auto-hospedagem é uma vantagem importante em relação às alternativas fechadas.

Conclusão

Next.js + Supabase é uma maneira poderosa e rápida de construir aplicativos full-stack em tempo real em 2026. Supabase fornece umbanco de dados PostgreSQL real, autenticação integrada e assinaturas em tempo real – emparelhando perfeitamente com Next.js. O fluxo de trabalho: criar tabelas com SQL, habilitar a segurança em nível de linha com políticas (crítica para acesso seguro direto do cliente), assinar alterações em tempo real e usar autenticação Supabase para usuários. Implante o front-end Next.js no Vercel e, como o Supabase já está hospedado, você terá um aplicativo full-stack ativo, sem infraestrutura de back-end para gerenciar. A principal regra de segurança é sempre ativar o RLS — é o que mantém seguros os dados acessados diretamente. Para bate-papo, ferramentas colaborativas, painéis e MVPs, essa pilha permite que você crie aplicativos full-stack em tempo real de maneira extremamente rápida, sem criar ou gerenciar um back-end.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা