supabase/supabase-flutter/supabase-flutter-realtime
- community
Checking that the SKILL.md file is still in the repository.
Builds realtime features with supabase_flutter v3: live lists of table rows with typed stream(), reacting to inserts, updates and deletes with onTableChanges, broadcast messages between clients, presence, and channel status and cleanup. Use when the user wants live updates, a chat, cursors, an online indicator or notifications of database changes.
Install
npx vskill@latest install supabase/supabase-flutter/supabase-flutter-realtimeSKILL.md
Realtime with supabase_flutter
Choose the API
| Need | Use | |
|---|---|---|
| The current rows of a table, kept up to date | table(X.table).stream(primaryKey: [...]) | |
| Only some columns of those rows | table(X.table).streamOnly(...) | |
| Every insert, update or delete as an event | channel.onTableChanges(X.table) | |
| Messages between clients that are not stored in a table | channel.onBroadcast and sendBroadcastMessage | |
| Who is online | channel.track and onPresenceSync |
Rules
- Every listener is a
Stream. There are nocallback:parameters. - Create every
onTableChanges,onBroadcastand presence stream before
channel.subscribe(). A postgres changes listener added after it throws a StateError.
- Cancel the subscriptions and call
supabase.removeChannel(channel)when the
feature is closed. A forgotten channel keeps receiving messages.
supabase.channel(name)returns the channel already open under that name,
and ignores the options passed with it. Remove the channel before reusing its name with other options.
- Use the typed table definitions from the generated schema, not table names
as strings.
- Database changes only arrive for tables in the
supabase_realtime
publication, and only for rows the user may select under row level security.
- Create streams once, in
initStateor a field ofState, never in
build(), or every rebuild opens a new subscription.
A live list of rows
stream() fetches the matching rows, then applies every change, and emits the whole list each time:
filter() takes one operator: eq, neq, lt, lte, gt, gte, inFilter, like, ilike, matchRegex, imatchRegex, isNull, isTrue, isFalse or isDistinct, optionally negated with not(). A filter composed with & or | throws an ArgumentError.
order() takes the same orderings as a query, Books.title or Books.createdAt.desc(). A stream keeps NULLs last ascending and first descending, so .nullsFirst(), .nullsLast(), or an ordering by anything but a stored column, such as a computed field, throws an ArgumentError.
To receive only some columns:
Reacting to changes
Without event, the stream carries TypedPostgresInsert, TypedPostgresUpdate and TypedPostgresDelete, so switch over all three. The old row of an update or delete only carries the primary key, unless the table has replica identity full. onTableChangesOnly(…, columns: [...]) asks the server for fewer columns.
Broadcast
Every onBroadcast message is a map with type, event and the sent data under payload, whether it came from sendBroadcastMessage, httpSend, the database or another Supabase client. Pass binary data such as a Uint8List as the payload itself to send it as a binary frame.
Pass RealtimeChannelConfig(self: true) as options to supabase.channel to receive your own broadcasts, and private: true for a channel guarded by realtime authorization policies.
Presence
Track only after the channel is subscribed, as above. untrack() removes the current client's state.
Status, errors and cleanup
onStatusChange reports the subscription status. A failure, such as a join the server declined, is a channelError status that carries the RealtimeException as change.error, not an error of the stream:
supabase.removeAllChannels() closes every channel, for example on sign out. A typed stream() reports its failures, including a RealtimeException, as errors of the stream itself, and keeps running: a failed fetch is retried, and a dropped connection is not reported, since the rows are fetched again once the channel rejoins. A client error that a retry cannot fix, such as a missing table, closes the stream.
The app lifecycle
Supabase disconnects the realtime socket when the app is paused and reconnects, rejoining every channel, when it resumes. Keep the socket open through short pauses, such as a full-screen ad on iOS, with RealtimeLifecycleOptions:
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/supabase_flutter/skills/supabase-flutter-realtime/SKILL.md
Popularity
- Repository stars
- 1,039
- Repository forks
- 312
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/supabase/supabase-flutter/supabase-flutter-realtime)