Dashboard

Live chat

Messages table with realtime inserts and an optional presence channel.

1. Schema

schema.sql
CREATE TABLE messages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  room TEXT NOT NULL,
  author TEXT NOT NULL,
  body TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Enable the table under dashboard Realtime.

2. Realtime

Pick your framework — selection is remembered across examples.

app/chat/page.tsx
'use client';

import { useEffect, useState } from 'react';
import { createClient } from 'voltbase-js';

const voltbase = createClient(
  process.env.NEXT_PUBLIC_VOLTBASE_URL!,
  process.env.NEXT_PUBLIC_VOLTBASE_ANON_KEY!,
);

type Message = { id: string; author: string; body: string };

export default function ChatPage() {
  const [messages, setMessages] = useState<Message[]>([]);

  useEffect(() => {
    const unsub = voltbase.realtime.subscribe(
      'messages',
      (event) => {
        if (event.type === 'INSERT') {
          setMessages((prev) => [...prev, event.record as Message]);
        }
      },
      { event: 'INSERT', filter: { room: 'lobby' } },
    );
    return () => unsub();
  }, []);

  async function send(body: string) {
    await voltbase.from('messages').insert({
      room: 'lobby',
      author: 'alice',
      body,
    });
  }

  return (
    <div>
      <ul>
        {messages.map((m) => (
          <li key={m.id}>
            <strong>{m.author}</strong>: {m.body}
          </li>
        ))}
      </ul>
      <button onClick={() => void send('Hello!')}>Send</button>
    </div>
  );
}

3. Presence

lib/presence.ts
const channel = voltbase.realtime.channel('lobby');

channel
  .on('presence', { event: 'sync' }, ({ state }) => {
    console.log('online', state);
  })
  .subscribe();

channel.track({ user: 'alice' });
Presence is in-memory on a single API instance — fine for demos and single-replica deploys.