Supabase.Realtime
8.0.0
dotnet add package Supabase.Realtime --version 8.0.0
NuGet\Install-Package Supabase.Realtime -Version 8.0.0
<PackageReference Include="Supabase.Realtime" Version="8.0.0" />
<PackageVersion Include="Supabase.Realtime" Version="8.0.0" />
<PackageReference Include="Supabase.Realtime" />
paket add Supabase.Realtime --version 8.0.0
#r "nuget: Supabase.Realtime, 8.0.0"
#:package Supabase.Realtime@8.0.0
#addin nuget:?package=Supabase.Realtime&version=8.0.0
#tool nuget:?package=Supabase.Realtime&version=8.0.0
Supabase.Realtime
A C# client for Supabase Realtime — listen to Postgres changes, and use Broadcast and Presence over a single websocket connection. It is a C#-ification of realtime-js.
Part of the Supabase C# SDK. Most projects
use it through the Supabase meta-package (supabase.Realtime); reference
this package directly to use Realtime on its own.
Installation
dotnet add package Supabase.Realtime
Targets .NET Standard 2.0 and 2.1.
Getting started
ConnectAsync() and Subscribe() are awaitable, so you can be sure a connection exists before
interacting with it. On the initial connection the client is fail-fast — ConnectAsync() throws a
RealtimeException if the socket server is unreachable. Once connected, it reconnects indefinitely
until disconnected.
using Supabase.Realtime;
var client = new Client("ws://realtime-dev.localhost:4000/socket");
await client.ConnectAsync();
// Shorthand for a postgres_changes subscription: database, schema, table
var channel = client.Channel("realtime", "public", "todos");
channel.AddPostgresChangeHandler(ListenType.Updates, (_, change) =>
{
var updated = change.Model<Todo>();
var previous = change.OldModel<Todo>();
});
await channel.Subscribe();
Todo derives from Supabase.Postgrest.Models.BaseModel, letting the client coerce change payloads
into your model via change.Model<T>().
Full generated API reference: Supabase.Realtime.
Postgres changes
Listen to inserts, updates, and deletes on a table, delivered to authorized clients according to your
Row Level Security policies. The table
must belong to the supabase_realtime publication.
More on Postgres changes.
var channel = client.Channel("public-users");
channel.Register(new PostgresChangesOptions("public", "users"));
channel.AddPostgresChangeHandler(ListenType.All, (_, change) =>
{
switch (change.Event)
{
case EventType.Insert: /* row created */ break;
case EventType.Update: /* row updated */ break;
case EventType.Delete: /* row deleted */ break;
}
});
await channel.Subscribe();
Broadcast
Publish-subscribe messaging: a client sends messages to a named channel, and any other client subscribed to that channel receives them in real time — useful for ephemeral, high-frequency data like cursor positions. More on Broadcast.
Given a typed broadcast model:
class MouseBroadcast : BaseBroadcast<MouseStatus> { }
class MouseStatus
{
[JsonProperty("mouseX")] public float MouseX { get; set; }
[JsonProperty("mouseY")] public float MouseY { get; set; }
[JsonProperty("userId")] public string UserId { get; set; }
}
Receive typed broadcast events:
var channel = client.Channel("cursor");
var broadcast = channel.Register<MouseBroadcast>(broadcastSelf: true);
broadcast.AddBroadcastEventHandler((_, _) =>
{
var state = broadcast.Current();
Debug.WriteLine($"{state.Payload.MouseX}:{state.Payload.MouseY}");
});
await channel.Subscribe();
Send a broadcast event on the same broadcast handle:
await broadcast.Send("cursor", new MouseBroadcast
{
Payload = new MouseStatus { MouseX = 123, MouseY = 456 }
});
Presence
Presence tracks shared state across clients using a CRDT: each client publishes its own state, and all subscribers converge on the same view. When a client disconnects, its state is removed automatically — which makes "who's online" features straightforward. More on Presence.
Given a typed presence model:
class UserPresence : BasePresence
{
[JsonProperty("lastSeen")] public DateTime LastSeen { get; set; }
}
Receive presence sync events:
var presenceId = Guid.NewGuid().ToString();
var channel = client.Channel("last-seen");
var presence = channel.Register<UserPresence>(presenceId);
presence.AddPresenceEventHandler(EventType.Sync, (_, _) =>
{
foreach (var state in presence.CurrentState)
{
var userId = state.Key;
var lastSeen = state.Value.First().LastSeen;
Debug.WriteLine($"{userId}: {lastSeen}");
}
});
await channel.Subscribe();
Track this client's presence:
presence.Track(new UserPresence { LastSeen = DateTime.Now });
Events and logging
Event handlers are delegates, scoped to the object they concern — socket handlers receive
connectivity events, channel handlers receive join/leave events, and so on. Register and remove them
with the Add/Remove/Clear methods (e.g. RealtimeSocket.AddStateChangedHandler,
RealtimeChannel.AddPostgresChangeHandler, RealtimeBroadcast.AddBroadcastEventHandler).
For logging, attach a debug handler rather than relying on console output:
client.AddDebugHandler((sender, message, exception) => Debug.WriteLine(message));
Observability: unlike the HTTP-based Supabase clients, Realtime is not yet instrumented for OpenTelemetry, so no websocket traces or metrics are emitted.
Contributing
Contributions are welcome. See the repository root for how to build and test the SDK.
Note that the Realtime test suite expects realtime-dev.localhost to resolve locally — add a hosts
entry for 127.0.0.1 realtime-dev.localhost.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Supabase.Core (>= 8.0.0)
- Supabase.Postgrest (>= 8.0.0)
- System.Text.Json (>= 8.0.5)
- Websocket.Client (>= 5.5.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Supabase.Realtime:
| Package | Downloads |
|---|---|
|
Supabase
A C# implementation of the Supabase client |
GitHub repositories
This package is not used by any popular GitHub repositories.