# Realtime

Scribase Realtime provides WebSocket subscriptions over Postgres logical
replication. Clients subscribe to table changes, broadcast messages, or track
presence — all through a single WebSocket connection.

## Channels

A **channel** is a named subscription topic. Three channel types are supported:

| Type | Description |
|---|---|
| `postgres_changes` | Subscribe to INSERT/UPDATE/DELETE on a Postgres table |
| `broadcast` | Pub/sub message passing between clients |
| `presence` | Track which clients are online in a channel |

## Subscribing to database changes

```ts
import { createClient } from '@supabase/supabase-js';

const scribase = createClient(
  'https://<your-project-url>',
  '<anon-key>'
);

scribase
  .channel('orders')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'orders' },
    (payload) => {
      console.log('Change received!', payload);
    }
  )
  .subscribe();
```

The `event` filter can be `'*'`, `'INSERT'`, `'UPDATE'`, or `'DELETE'`.

## Row-level filtering

Subscriptions respect RLS policies — clients only receive changes for rows
their JWT is authorized to see.

You can also add a `filter` string for server-side filtering:

```ts
.on('postgres_changes', {
  event: 'INSERT',
  schema: 'public',
  table: 'messages',
  filter: 'channel_id=eq.42',
}, handler)
```

## Broadcast

Send messages to all subscribers of a channel without touching the database:

```ts
const channel = scribase.channel('room:42');

channel.on('broadcast', { event: 'typing' }, (payload) => {
  console.log(payload.userId, 'is typing');
});

await channel.subscribe();

// Send
channel.send({ type: 'broadcast', event: 'typing', payload: { userId: 'alice' } });
```

## Presence

Track which clients are currently subscribed to a channel:

```ts
const channel = scribase.channel('room:42');

channel.on('presence', { event: 'sync' }, () => {
  const state = channel.presenceState();
  console.log('Online users:', state);
});

await channel.subscribe();
await channel.track({ user: 'alice', online_at: new Date().toISOString() });
```

## RLS and security

- Realtime respects your Postgres RLS policies. A subscriber only receives
  events for rows they can SELECT.
- For public events (no auth), use a public table or an open policy.
- The anon key authorizes subscriptions as the anonymous role.

## HTTP API (management)

The realtime management API is accessible via the SDK:

```ts
const { channels } = await scribase.realtime.listChannels(ref);
```

## Local development

`scribase dev` starts the Realtime service automatically. Connect to:

```
ws://localhost:8000/realtime/v1/websocket?apikey=<anon-key>
```
