Community

Wallets

zap.stream

zap.stream is where Nostr's social graph becomes a live room: `kind 30311` stream events, `kind 1311` chat, Lightning zaps, OBS hosting, mobile broadcasting and a provider market that still has to prove it can survive real video traffic.

zap.stream: a focused visual for this route.
Route Value flow you can carry Zaps, Lightning, wallet connect, Safebox and sovereign records.
Back to Nostr
Wallets

Wallets shelf

Wallet pages collect zaps, Lightning, Nostr Wallet Connect, Cashu, spending permissions and the social value layer.

Wallets All Wallets pages 55 pages in this routeApp pages, App profiles, Awesome Nostr branches and 6 more shelves Browse pagesClose shelf

App profiles

App pages

Wallets and value flow

Deep dives

Field guides

Awesome Nostr branches

NIP explainer pages

NIP reference pages

Source inventory

Apps31 min readlive streaming, zaps and provider infrastructure

zap.stream

zap.stream is a Nostr live-streaming client, a zap-native audience room, a hosted RTMP/HLS provider, a developer API and a mobile app effort. It is also a good test of where Nostr is strong and where video still forces somebody to run serious infrastructure.

The quick readzap.stream is not Twitch with a purple bolt painted on it. The public client reads and writes NIP-53 live-stream events, its hosted provider gives streamers OBS-ready RTMP endpoints, chat uses Nostr events, zaps use NIP-57 receipts, uploads lean on Blossom and Route96, and the whole thing is maintained by Kieran/v0l with a growing Flutter app and a self-hostable Rust backend.

Live streaming is not a social post

Live video is one of the least forgiving things you can ask an open social protocol to carry. A note can arrive late. A profile picture can fail and reload. A marketplace listing can be copied to another relay. A live stream is different. People show up at the same time, expect moving video, send chat in seconds, tip in public, ask for moderation, and leave immediately if the player buffers. That is why zap.stream matters. It is a serious attempt to make Nostr feel live, not just archived.

The official site calls it Nostr live streaming powered by Bitcoin Lightning. The README is more exact: it is a NIP-53 Nostr client. NostrApps compresses the pitch to "Live stream and zap" and lists the user-facing jobs: start a livestream through zap.stream or Cloudflare, watch livestreams, chat, use custom emojis, zap streamers and chat participants in real time, and set up stream goals. Those small bullets are a useful map of the product. zap.stream is not just a video player. It is a live room where identity, stream metadata, chat, goals and payments are all supposed to be signed or at least legible to Nostr.

The public project trail points to Kieran, GitHub user `v0l`, in Ireland. The `v0l/zap.stream` repository was created on September 1, 2023, is MIT licensed, is written primarily in TypeScript, and was still being pushed in April 2026. GitHub metadata on June 7, 2026 showed 62 stars, 20 forks and seven open issues. That is not giant-platform scale. It is the scale of an active Nostr builder carrying a sharp product through real usage.

The current web app is a Vite/React application with a PWA manifest, service worker, route-level pages for streams, videos, shorts, categories, providers, dashboard, uploads, widgets, FAQ and terms. On June 7, 2026 the live home page rendered active categories such as IRL, Gaming, Music, Talk and Art, and showed actual live streams such as Synthdragon Radio and RetroStrange TV. The first load produced two browser warnings, then the interface hydrated and displayed the stream grid. That matters because this is not an abandoned catalog listing. It is a live site with current relay and provider behavior.

The useful way to read zap.stream is to split it into four layers. First, the Nostr layer: `kind 30311` live events, `kind 1311` chat, `kind 1312` raids, `kind 1313` clips, `kind 9041` goals and `kind 9735` zap receipts. Second, the media layer: RTMP ingest, HLS playback, m3u8 playlists, stream keys, recorded streams, clips and Blossom-backed uploads. Third, the wallet layer: Lightning addresses, LNURL, NIP-57, optional WebLN/wallet payment, provider top-up, withdrawal and NWC configuration. Fourth, the operational layer: stream providers, TOS, pricing, API authentication, caching edges, deletion, moderation and support. If one layer fails, the whole room feels broken.

What zap.stream publishes

The center of zap.stream is NIP-53, the live activities specification. In the current NIPs repository, NIP-53 uses `kind 30311` for live events. zap.stream's API constants file names that exact value as `LIVE_STREAM = 30_311`, keeps a legacy or alternate `N94_LIVE_STREAM = 1053`, and defines adjacent product kinds: `LIVE_STREAM_CHAT = 1_311`, `LIVE_STREAM_RAID = 1_312`, `LIVE_STREAM_CLIP = 1_313` and `GOAL = 9041`. That is the skeleton of the app.

A stream is not merely a URL. The stream editor writes an addressable live event with a `d` tag, `title`, `summary`, `image`, `status`, `starts`, tags, content warning, optional goal and a `streaming` tag when the status is live. When a stream ends, it can add an `ends` timestamp and a `recording` tag. That means a stream can be pointed to by a Nostr address, updated over time, and discovered by clients that understand the event kind and tags. A regular HLS player only knows the stream URL. Nostr adds the host key, the title, the social context and the replay trail.

zap.stream reads from a broad default relay set: `wss://relay.snort.social`, `wss://nos.lol`, `wss://relay.damus.io`, `wss://nostr.wine`, `wss://relay.primal.net`, `wss://relay.fountain.fm` and `wss://relay.divine.video/`. The code also has a `WHITELIST` option for single-publisher deployments and a `P_TAG_HOST_WHITELIST` for pubkeys allowed to use a host tag. The `ZAP_STREAM_PUBKEY` constant hardcodes the zap.stream service pubkey as `cf45a6ba1363ad7ed213a078e710d24115ae721c9b47bd1ebf4458eaefb4c2a5`. The whitelist also names Primal Stream, Streamstr and Shosho streaming server keys. That is a practical compromise: an open live feed needs discovery, but a hosted streaming service also needs to know which infrastructure is allowed to assert itself as a host.

A relay spot check on June 7, 2026 found real `kind 30311` events on relay.snort.social, nos.lol, relay.damus.io, nostr.wine, relay.primal.net and relay.fountain.fm. Some events were ended streams published by zap.stream's service pubkey. Others were current live streams with `status=live`, `streaming` HLS URLs and `d` identifiers, including radio-style streams. relay.divine.video opened but did not return samples in that small check. That is a healthy sign, with a caveat: live discovery depends on relay availability, cache freshness and clients handling both current and stale events correctly.

Chat is not an iframe bolted to the side. The live chat code reads `kind 1311` events, replies them to the stream address and supports custom emoji packs, muted pubkeys, badges, top zappers and external chat bridges. A second relay check found `kind 1311` messages tied to `30311:pubkey:d` addresses, including messages that identify clients such as Amethyst, Wisp and Corny Chat. The product idea is bigger than zap.stream alone: if other clients agree on the event shape, live chat can become portable social data rather than a proprietary transcript.

Raids and clips stretch that model further. The `kind 1312` raid events sampled in the relays used `a` tags to point from one live event to another, usually with `root` and `mention` markers. The `kind 1313` clip samples included alt text and URLs to DVR-style clip files. That is a real live-platform behavior translated into Nostr: send the room somewhere else, preserve a moment, make it addressable. It is also where the boundary of standards gets thin. NIP-53 covers the core live activity, but zap.stream's surrounding kinds are product conventions that other clients may or may not implement cleanly.

Why the zap part matters

The word "zap" is not decoration. A livestream has a different emotional rhythm from a post. When someone says something useful in chat, wins a match, plays a song, finishes a talk or hits a funding goal, the payment impulse is immediate. Nostr's NIP-57 zap model lets that payment become a social receipt: a payer, receiver, target event, Lightning invoice and optional comment can be tied together in a way other clients can read.

zap.stream's zap component builds that into the room. It offers preset sats amounts from tiny 21-sat gestures through much larger amounts, fiat conversion display, custom amounts, comments, optional anonymous tagging, LNURL invoice generation and wallet payment when a wallet is available. When the zap targets a stream, the code can attach `a` or `e` tags to the zap request so the payment is connected to a live event or message. The app then reads `kind 9735` ZapReceipt events with `useZaps`, parses them and filters for valid receipts.

That design has a strong creator-side consequence: the audience does not merely clap. It funds the room while the room is still alive. The `Goal` component reads a `kind 9041` goal event, looks for an `amount` tag in millisats, sums valid zaps where the receiver and target match, and displays progress. In sampled relays, `kind 9041` goals appeared with amounts and client tags. That is the part of zap.stream that Nostr is unusually good at: the money, public proof and social context can be one visible object.

The wallet flow is still not magic. The app can load a configured wallet from the login session or fall back to `window.webln` through the `@snort/wallet` abstraction. It also has a provider account top-up flow that asks the stream provider for a Lightning invoice, then routes payment through the same SendZaps UI. Provider withdrawal exists too: the UI can take a BOLT11 invoice or a Lightning address, check whether the provider supports withdrawal, and call the provider endpoint. This is useful, but it means a streamer has at least three balances to reason about: their personal Lightning wallet, their zap receipts, and their streaming provider account balance.

NWC appears as a provider configuration layer rather than the only wallet path. The `nwc-config.tsx` component accepts a `nostr+walletconnect://` URI, configures or removes NWC on the stream provider, and presents success or error states. The related NIP-47 context matters because NWC can let a service trigger wallet actions without putting a full wallet inside the streaming client. It is powerful, but it must be permissioned carefully. A streaming dashboard that spends, tops up, withdraws and listens to live payments needs boring controls, clear budgets and obvious revocation.

Hosting is the hard part

The FAQ makes the streamer flow plain. Log in, create an account if needed, click Stream, choose between zap.stream's in-house hosting or a manual setup such as Cloudflare, then copy the stream URL and Stream Key into OBS. That sentence hides the hard part. Nostr can publish the event, but it does not transcode video, serve HLS segments, maintain an RTMP ingress, price bandwidth, remove illegal content, recover broken recordings or keep the m3u8 endpoint over HTTPS. Someone has to run that machinery.

In the current web client, the default provider config is `zap.stream` at `https://api-core.zap.stream/api/v1`, with the public zap.stream service pubkey. The provider API package, `@zap.stream/api`, is designed to be Nostr-library independent: bring a signer that can return a pubkey and sign an event. The provider client then uses NIP-98-style HTTP authentication with `kind 27235`, `u` and `method` tags, and a base64-encoded signed event in the Authorization header. It also authenticates a WebSocket connection for stream metrics. This is an important design choice. The provider service is centralized infrastructure, but its account actions are gated by Nostr signatures rather than ordinary passwords.

The `@zap.stream/api` README exposes the account model: check balance, list endpoints, show stream URL, stream key and cost, top up with Lightning, withdraw, read balance history, manage stream keys and talk to real-time metrics. The dashboard code mirrors that: it fetches provider info, chooses a default endpoint, displays RTMP information, estimates balance time, shows metrics, supports raid actions and can open provider settings. The terms page is honest that the TOS applies to zap.stream-provided streaming providers, not to every HLS URL somebody publishes through the client.

zap.stream is also becoming more provider-market than single server. The live providers page on June 7, 2026 listed the official zap.stream provider, alternative zap.stream CA and UK providers, Streamstr in Germany, Let's Fo Live, Tony Live and Solomon Live. Several cards produced a signerless error when viewed without login, which is exactly what you would expect when provider details require a Nostr signer. The Shosho documentation describes adding Zap Stream Server inside Shosho with the API URL `https://api-core.zap.stream/api/v1`, then letting Shosho connect to that Nostr-aware provider. That is the most useful direction for the ecosystem: multiple clients can point at multiple streaming backends instead of pretending that Nostr itself transcodes video.

The self-hosting trail is visible in `v0l/zap-stream-core`, a Rust backend created in August 2024. Its README says the easiest deployment path is Docker Compose and calls out the values an operator must set: admin pubkey, public API URL, endpoint hostname for RTMP, an overseer nsec for publishing stream events, database credentials, payment backend and provider advertising. It binds public HTTP and RTMP ports and needs valid TLS for browser playback. The same repo includes an N94 broadcaster that can ingest RTMP, SRT or test patterns, transcode to variants, publish segments to Blossom servers and broadcast stream events to Nostr relays. In plain language: zap.stream has a plausible path away from one hosted service, but only for people willing to run video infrastructure.

Keys, accounts and the risky comfort layer

zap.stream's login model is a mix of sensible Nostr practice and convenience risk. The FAQ recommends a Nostr extension such as nos2x or Alby. The code uses `Nip7Signer` for NIP-07 browser extension login and `PrivateKeySigner` for private-key login. The signup flow can generate a random private key, collect profile details, set a Lightning address, publish the profile and then show a Save Key step. It can also accept an `nsec` or hex private key for login.

The risky detail is storage. `LoginStore` reads and writes a `session` object in `window.localStorage`. That session can include login type, pubkey, private key, serialized user state, color and wallet data. For a NIP-07 session, the private key is not in the zap.stream app. For a PrivateKey session, it can be. That is a real tradeoff. A live-streaming app wants fast login, chat, zaps, dashboard actions and mobile-style continuity. A user should still treat direct private-key login as a high-trust mode and prefer an external signer where possible.

This account model also interacts with lists. Issue #19 says following npubs from inside zap.stream deletes follows outside zap.stream; it remained open in the issue list. That is not a small UI bug in Nostr. Follow lists are not a private local preference; they are public social state. If one client overwrites a list in a way another client does not expect, the user feels the cost across their whole identity. A good Nostr app should be conservative when it edits shared lists.

There is a similar caution around NWC and relay authentication. Issue #13 says the NWC relay client should reply to AUTH challenge. That issue remained open in the GitHub issue list. The practical point is not that zap.stream is broken; it is that a wallet-connected live app sits at the intersection of multiple moving specs: NIP-07, NIP-47, NIP-57, NIP-98 and relay AUTH. Users should keep wallet budgets low, understand which provider they are using, and avoid treating a streaming dashboard as a cold wallet.

Media, clips and mobile

zap.stream also has a second product hiding inside the live product: uploaded and recorded media. The app includes routes for videos, shorts and uploads. The upload page uses Blossom servers from the user's `BlossomServerList`; if none are configured, it defaults to `https://nostr.download/`. The `Blossom` service code computes a SHA-256 hash, signs a Blossom auth event of kind `24242`, sends an Authorization header and receives a blob descriptor with URL, size, type and optional NIP-94 tags. The upload page then turns metadata into imeta-style tags for video or shorts publishing.

That route points directly to `v0l/route96`, the server behind nostr.download. Route96 describes itself as a decentralized blob storage server with Nostr integration, supporting NIP-96, Blossom BUDs, NIP-94 metadata, thumbnail generation, range requests, media metadata, AI labeling, reports and a review queue. NIP-96 is now marked in the NIPs repository as deprecated in favor of NIP-B7, but Route96 still matters because actual media clients have to survive old and new storage conventions. For zap.stream, Blossom is not an academic standards footnote. It is how covers, uploads, clips and related media stop being just a URL pasted into a form.

Clips make this tangible. The clip button only appears when a stream is live and tied to a provider service. It can call a provider clip endpoint with a stream id, temporary clip id, start and length, then publish a `kind 1313` event with an `a` tag pointing back to the live event, an `alt` tag explaining that the clip was created on zap.stream, a resource URL and a title. Relay samples showed old zap.stream clips with DVR URLs and titles. That is the right shape for a live product: the room produces artifacts that can travel after the room closes.

The mobile story is newer. The web repo's download page links to Google Play package `io.nostrlabs.zap_stream_flutter`, a TestFlight invite and the `nostrlabs-io/zap-stream-flutter` repository. GitHub metadata on June 7, 2026 showed that Flutter repo was created in May 2025, written in Dart, pushed in April 2026 and had 11 stars, two forks and 12 open issues. OpenSats' Nostr client update also places Kieran's work in a broader grant context and mentions zap.stream iOS/Android releases, zap-stream-core and Route96. The safe reading is this: zap.stream is no longer only a web page, but the mobile product is still part of an active builder stack rather than a mature mass-market app.

Where it can break

The most important risk is not that zap.stream is centralized or decentralized. It is that it is both. Nostr makes the stream event, chat, zaps, goals and some media metadata portable. The actual video path still depends on providers, endpoints, TLS, RTMP, transcoding, HLS playlists, edge caches and storage. A stream can be represented on relays and still fail to play. A zap can prove payment and still leave a creator confused about their provider balance. A chat can be public and portable and still be unpleasant without moderation.

The issue tracker shows the texture of real product work. There were older issues around going live, stream keys, video concatenation, VOD lifecycle, mobile stream view, HTTP calls to `us0.edge.zap.stream`, Cloudflare errors, stream cover saving, widgets, channel URLs, ended streams appearing live, stream info updates and support. Some are closed, which is healthy. The open issues are instructive: Google Cast support was requested and later tied to a PR, NWC AUTH remained open, follow-list overwrite remained open, deleting past streams had an issue before a deletion PR landed later, message decay for widgets remained open, chat loading had an open PR, and issue #60 described chat message bleed across channels.

Moderation deserves special attention. Nostr helps with identity and censorship resistance, but live video is a moderation accelerator. The zap.stream TOS prohibits rights-infringing content and reserves the right to suspend or terminate access to the service. Route96 has reporting, flagging and review concepts. That is not hypocrisy. It is the operational reality of running public media infrastructure. If you use zap.stream only as a NIP-53 client with your own HLS URL, the operator has less control. If you use zap.stream's provider, you are using their infrastructure and their terms.

The strongest test for a creator is simple. Open a stream event in zap.stream, then look for the same event on another Nostr client or relay tool. Check that the `kind 30311` event has the title, status, `streaming`, `d` and host tags you expect. Send a small zap and verify the `kind 9735` receipt points to the correct event or person. Send a harmless chat message and confirm it is a `kind 1311` reply to the stream address. If you stream through a hosted provider, keep enough balance for your planned run, copy the stream key carefully into OBS, and test whether a recording or clip survives after the live session ends.

For Crays, zap.stream is worth a serious place on the shelf because it is one of the few Nostr apps that forces every layer of the network to show up at once. Keys, relays, media, money, moderation and operational costs are all visible. That makes it exciting, but not simple. The promise is not "video without servers." The promise is a live room where the social proof, payment proof and stream identity are not locked inside one platform database.

Sources worth opening

This article keeps claims close to public project trails, live route checks, repository source and standards documents. Start here when you want to verify the product yourself.

Back to the Crays Nostr page
Wallets route visual cue 1
Wallets route visual cue 2
Wallets route visual cue 3
Wallets route visual cue 4
Wallets route visual cue 5

How to use this page

Use the wallet route when small value changes behavior.

Search zaps, wallet connections, Cashu, Lightning and Nostr Wallet Connect when payments become part of the experience.

WalletsThe full Wallets route stays open55 pages in this routeZaps, Lightning, NWC, Cashu and sovereign records.Browse pages
Wallets route visual cue 1
Wallets route visual cue 2
Wallets route visual cue 3
Wallets route visual cue 4
Wallets route visual cue 5

Bring something back

Ask, suggest, submit or nominate.

Ask a question, send a source, suggest a fix, submit a project or nominate a public Nostr account. The page stays stable; your contribution gets reviewed beside it.