{"id":13812237,"url":"https://github.com/supabase/realtime-js","last_synced_at":"2025-05-14T02:08:17.693Z","repository":{"id":40767901,"uuid":"264389263","full_name":"supabase/realtime-js","owner":"supabase","description":"An isomorphic Javascript client for Supabase Realtime server.","archived":false,"fork":false,"pushed_at":"2025-05-07T17:17:57.000Z","size":2018,"stargazers_count":350,"open_issues_count":33,"forks_count":68,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-05-07T17:45:32.373Z","etag":null,"topics":["hacktoberfest"],"latest_commit_sha":null,"homepage":"https://supabase.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/supabase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["supabase"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-05-16T08:08:00.000Z","updated_at":"2025-05-05T09:50:10.000Z","dependencies_parsed_at":"2023-09-23T05:11:49.390Z","dependency_job_id":"5507dae4-d8d3-45cb-8b04-a9e36b3ac35d","html_url":"https://github.com/supabase/realtime-js","commit_stats":{"total_commits":246,"total_committers":29,"mean_commits":8.482758620689655,"dds":0.6178861788617886,"last_synced_commit":"ff9421ca29b032f73cd480899a74a1860c5925c3"},"previous_names":[],"tags_count":124,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supabase%2Frealtime-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supabase%2Frealtime-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supabase%2Frealtime-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/supabase%2Frealtime-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/supabase","download_url":"https://codeload.github.com/supabase/realtime-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254053152,"owners_count":22006717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest"],"created_at":"2024-08-04T04:00:49.629Z","updated_at":"2025-05-14T02:08:17.636Z","avatar_url":"https://github.com/supabase.png","language":"TypeScript","readme":"\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://supabase.io\"\u003e\n        \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg\"\u003e\n      \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg\"\u003e\n      \u003cimg alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\n  \u003ch1 align=\"center\"\u003eSupabase Realtime Client\u003c/h1\u003e\n\n  \u003ch3 align=\"center\"\u003eSend ephemeral messages with \u003cb\u003eBroadcast\u003c/b\u003e, track and synchronize state with \u003cb\u003ePresence\u003c/b\u003e, and listen to database changes with \u003cb\u003ePostgres Change Data Capture (CDC)\u003c/b\u003e.\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://supabase.com/docs/guides/realtime\"\u003eGuides\u003c/a\u003e\n    ·\n    \u003ca href=\"https://supabase.com/docs/reference/javascript\"\u003eReference Docs\u003c/a\u003e\n    ·\n    \u003ca href=\"https://multiplayer.dev\"\u003eMultiplayer Demo\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n# Overview\n\nThis client enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\nnpm install @supabase/realtime-js\n```\n\n## Creating a Channel\n\n```js\nimport { RealtimeClient } from '@supabase/realtime-js'\n\nconst client = new RealtimeClient(REALTIME_URL, {\n  params: {\n    apikey: API_KEY\n  },\n})\n\nconst channel = client.channel('test-channel', {})\n\nchannel.subscribe((status, err) =\u003e {\n  if (status === 'SUBSCRIBED') {\n    console.log('Connected!')\n  }\n\n  if (status === 'CHANNEL_ERROR') {\n    console.log(`There was an error subscribing to channel: ${err.message}`)\n  }\n\n  if (status === 'TIMED_OUT') {\n    console.log('Realtime server did not respond in time.')\n  }\n\n  if (status === 'CLOSED') {\n    console.log('Realtime channel was unexpectedly closed.')\n  }\n})\n```\n\n### Notes:\n\n- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://\u003cproject_ref\u003e.supabase.co/realtime/v1'` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```js\n// Setup...\n\nconst channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })\n\nchannel.on('broadcast', { event: 'some-event' }, (payload) =\u003e\n  console.log(payload)\n)\n\nchannel.subscribe(async (status) =\u003e {\n  if (status === 'SUBSCRIBED') {\n    // Send message to other clients listening to 'broadcast-test' channel\n    await channel.send({\n      type: 'broadcast',\n      event: 'some-event',\n      payload: { hello: 'world' },\n    })\n  }\n})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgement that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```js\n// Setup...\n\nconst channel = client.channel(\n  'presence-test',\n  {\n    config: {\n      presence: {\n        key: ''\n      }\n    }\n  }\n)\n\nchannel.on('presence', { event: 'sync' }, () =\u003e {\n  console.log('Online users: ', channel.presenceState())\n})\n\nchannel.on('presence', { event: 'join' }, ({ newPresences }) =\u003e {\n  console.log('New users have joined: ', newPresences)\n})\n\nchannel.on('presence', { event: 'leave' }, ({ leftPresences }) =\u003e {\n  console.log('Users have left: ', leftPresences)\n})\n\nchannel.subscribe(async (status) =\u003e {\n  if (status === 'SUBSCRIBED') {\n    const status = await channel.track({ 'user_id': 1 })\n    console.log(status)\n  }\n})\n```\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```js\n// Setup...\n\nconst channel = client.channel('db-changes')\n\nchannel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) =\u003e {\n  console.log('All changes in public schema: ', payload)\n})\n\nchannel.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, (payload) =\u003e {\n  console.log('All inserts in messages table: ', payload)\n})\n\nchannel.on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' }, (payload) =\u003e {\n  console.log('All updates on users table when username is Realtime: ', payload)\n})\n\nchannel.subscribe(async (status) =\u003e {\n  if (status === 'SUBSCRIBED') {\n    console.log('Ready to receive database changes!')\n  }\n})\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiatied.\n\n```js\n// Setup...\n\nclient.getChannels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```js\n// Setup...\n\nconst channel = client.channel('some-channel-to-remove')\n\nchannel.subscribe()\n\nclient.removeChannel(channel)\n```\n\n- Remove all channels\n\n```js\n// Setup...\n\nconst channel1 = client.channel('a-channel-to-remove')\nconst channel2 = client.channel('another-channel-to-remove')\n\nchannel1.subscribe()\nchannel2.subscribe()\n\nclient.removeAllChannels()\n```\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n","funding_links":["https://github.com/sponsors/supabase"],"categories":["📦 Legacy \u0026 Inactive Projects","Realtime","TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupabase%2Frealtime-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsupabase%2Frealtime-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsupabase%2Frealtime-js/lists"}