zap.stream
zap.stream is where Nostr has to deal with the messy reality of live media: public stream events, chat, zaps, OBS keys, provider balances, mobile apps, clips, video storage, moderation, analytics and a streaming backend that still needs servers, payments and careful operations.
What zap.stream really is
zap.stream is best understood as a Nostr live-streaming client and provider stack. You open it to watch a live room, start a stream, publish stream metadata, chat around a live activity, send sats to a creator, create clips or browse recorded and uploaded video. That places it on the Media route and in the Live Streaming group, even though the payment layer is important enough to tempt a wallet classification.
The project is not trying to put raw video through Nostr relays. That distinction matters. Nostr carries the identity, live activity event, chat messages, zap receipts, goals, relay discovery and metadata that make a stream visible outside one platform database. The video itself still travels through ordinary media infrastructure: RTMP, HLS, provider endpoints, browsers, storage, bandwidth, players and sometimes transcoders.
This is why zap.stream is more interesting than a simple app listing. It forces every Nostr layer to show up at once. A streamer needs keys, a room object, a video path, a payment path and enough balance to keep provider hosting alive. A viewer needs a playable stream, relays that return the event, chat that is tied to the right live address and a wallet flow that does not spend more than intended.
For you as a reader, the useful question is not whether zap.stream is decentralized or centralized. It is both. The social object is portable enough to be read by other Nostr tools. The media path is still operational infrastructure. Good use starts by keeping those boundaries visible.
The live app is a stream directory
A browser check on June 13, 2026 showed `https://zap.stream/` serving a real app, not only a static splash page. The raw HTML advertises Nostr live streaming powered by Bitcoin Lightning and shows build `v0.5.0-109-g811e55f`. The loaded app presented a live stream directory, categories such as IRL, Gaming, Music, Talk and Art, and visible live cards with titles, npub-linked profiles and viewer counts.
That live surface matters because it proves zap.stream is not merely a code experiment. It is a public discovery UI where active streams can appear, including 24/7 radio-style channels and normal creator streams. The cards link to Nostr address routes and profile routes, which is exactly what a NIP-53 client should do: present the live room as a Nostr-addressed media object.
The app also carries a practical mobile prompt. The home page showed a callout for the new zap.stream app, while the source code for the download page points to Google Play, a TestFlight invite and the `nostrlabs-io/zap-stream-flutter` repository. That does not make the mobile apps mature by itself, but it shows the product is moving beyond a desktop web-only flow.
The visible operational caveat was also useful. The `/providers` route returned a Cloudflare Worker exception during the June 13 check, while the FAQ and terms routes rendered. A provider page outage is not a protocol failure, but it is exactly the kind of edge that matters in live streaming. If the provider market or account screen is unavailable, a creator may not be able to inspect costs, endpoints or hosting choices at the moment they need them.
NIP-53 is the core public object
The project's README is direct: zap.stream is a NIP-53 Nostr client. NIP-53 defines live activity events with kind 30311 and live chat messages with kind 1311. The live activity event is an addressable object that can carry a title, summary, image, tags, status, streaming URL, recording URL and participant information. That is the public handle for a live stream.
In the zap.stream code, live stream extraction reads `streaming`, `recording` and `url` tags, and stream editors can publish or update live events with a `d` tag, title, summary, image, status, content warning, stream URL, recording URL, topics and goal data. The stream page then chooses between a live stream URL and a recording URL based on the stream status.
This makes the Nostr part concrete. A stream is not only a page on zap.stream. It can be represented by an event that other clients, relays and tools can address. That is why routes often contain Nostr address encodings instead of ordinary numeric platform ids. The stream is meant to travel through the Nostr graph even though the video player still needs a normal media URL.
The caution is that NIP-53 gives the room a public shape; it does not guarantee that the media will play, that the recording survives, that the provider is paid or that every client understands every zap.stream extension. Treat the event as the index card for the live object, not as the whole production system.
Live chat, zaps and goals
zap.stream uses Nostr not only to announce a stream, but to build the room around it. The app listens for live chat, raid and clip kinds around a stream link, and it reads zap receipts alongside other activity. NIP-53's kind 1311 live chat model is the most important chat anchor because messages should point back to the live activity address with a root marker.
The zap behavior is what gives the product its name. NIP-57 defines zap requests and zap receipts as Nostr-visible Lightning payment records. zap.stream can attach zaps to a stream, a person, a chat moment or a goal, then show those receipts as part of the room. That is different from an ordinary donation button because the payment can become a social object.
The code also includes goal behavior around kind 9041. Goals let a streamer or community show funding progress during a live moment. That is one of Nostr's better fits: a live activity can have an address, a goal can target it, zaps can accumulate, and participants can see value move while the room is still happening.
Do not turn that into blind trust. A zap receipt proves a payment flow happened in relation to a Nostr event, subject to the wallet, relays and invoice path involved. It does not prove that a creator can withdraw from a provider balance, that an off-platform promise was fulfilled or that a fake stream is legitimate. In a live room, payments feel fast; verification still matters.
Streaming providers carry the hard cost
The FAQ describes the streamer flow in plain terms. Log in, create or use a Nostr account, click Stream, choose between zap.stream's in-house hosting or manual hosting such as Cloudflare, then copy the Stream URL and Stream Key into OBS. The recommended settings are conventional: H.264 video, AAC audio, up to 7000k video bitrate, up to 320k audio bitrate and a two-second keyframe interval.
That sounds simple because the difficult part has been moved into provider infrastructure. A Nostr relay can tell people that a stream exists. It cannot run the RTMP ingest, transcode, store HLS segments, serve video across regions, record DVR output, bill a streamer or recover from a broken encoder. The provider is where bandwidth, CPU, TLS, storage and abuse handling become real.
The current web client uses provider concepts throughout the dashboard. It can choose a streaming provider, display endpoints with different costs and capabilities, top up a balance, show metrics, configure settings and open stream account actions. This makes zap.stream more like a Nostr-aware Twitch studio plus provider market than a standalone feed client.
The June 13 Cloudflare error on `/providers` is therefore more than a tiny page glitch. It is a reminder that the provider layer is an application layer with its own uptime. Before a public event, do not wait until the start time to find your provider, endpoint and balance. Open the dashboard, confirm the stream key and run a short private test.
zap-stream-core exposes the machinery
`v0l/zap-stream-core` is the Rust backend that shows how serious the hosting side is. Its README calls it the streaming backend for zap.stream and points operators to Docker Compose deployment. The repo metadata checked on June 13, 2026 showed a Rust project created in August 2024, pushed on May 5, 2026, with 22 stars, seven forks and no license field in GitHub metadata. If you plan to reuse it, check licensing directly before assuming permissions.
The deployment docs list the pieces a streaming provider must care about: public Nostr relays for announcements and chat, optional Blossom servers for file storage, an LND backend for Lightning payments, public RTMP or SRT ingestion, HLS output, database credentials, payment backend configuration, public hostnames, TLS and monitoring. This is not a tiny sidecar service.
The core docs also make the economics explicit. Variants can create transcoded outputs, DVR recording adds storage, billing can occur by HLS segment, and payment types include top-ups, withdrawals and zaps. The examples mention streaming costs in millisatoshis per minute. A creator therefore has two money flows to separate: audience zaps and provider hosting balance.
That is the key operational lesson. Nostr makes the stream object portable, but the provider has to pay for and control the media pipe. If you self-host zap-stream-core, test RTMP ingress, HLS playback, certificates, payment accounting, logs, monitoring, storage growth, abuse response and rollback before inviting an audience.
NIP-98 protects provider actions
The `@zap.stream/api` package is useful because it separates the provider account model from a specific Nostr library. Its README says it has zero Nostr-library dependencies and expects a signer that can return a public key and sign an event. The provider client can then check account info, list endpoints, top up, withdraw, update stream details, read history, manage stream keys, create clips and subscribe to real-time metrics.
The authentication model is NIP-98 HTTP auth. The zap-stream-core API docs require an `Authorization: Nostr` header containing a base64-encoded kind 27235 event with a valid signature, method tag, URL tag and recent timestamp. WebSocket metrics also use NIP-98-style authentication after connection establishment. That keeps provider account actions tied to Nostr key control rather than an ordinary password.
This design is a good fit for Nostr, but it raises the stakes for signer hygiene. If a provider account can show stream keys, create invoices, withdraw funds, configure NWC or control stream details, signing prompts should be boringly clear. You should understand which domain is asking, which method and URL are being authorized and whether your signer can display that context.
For developers, the provider API is the bridge that lets other clients integrate with the streaming backend. For users, it is the reminder that a Nostr key can authorize more than posting a note. It can authorize account actions. That power is useful only if signer UX and revocation habits keep up.
NWC is a provider setting, not the whole product
Nostr Wallet Connect appears in zap.stream, but it should not be overdescribed as the core product. The main product is live streaming. NWC is a wallet automation and provider configuration path. The settings UI accepts a `nostr+walletconnect://` URI, validates the shape, configures or removes NWC for a provider account and displays success or error states.
The zap-stream-core API docs explain the intent more directly. Account settings can include an NWC URI, and the server validates that the connection has `pay_invoice` permissions. The docs describe NWC as a way to support automated withdrawal processing through a compatible Nostr wallet. That is powerful, but it is not the same thing as holding funds inside zap.stream.
The risk is obvious once you place it in the streaming context. A creator may be topping up provider balance, receiving zaps, paying for stream minutes, withdrawing funds and connecting a wallet automation URI. Those are separate controls. A good setup uses small test amounts, a wallet with limits, clear permissions and a revocation path that the user can find under stress.
This is why ZapStream belongs in Live Streaming while still needing a serious money section. The wallet layer is not decoration. It decides whether creators can afford to stay live and whether support reaches them safely. It just is not the primary user action.
Keys and login choices
The web app supports the normal Nostr extension path through `window.nostr` and NIP-07-style signing. The FAQ recommends a Nostr extension such as nos2x or Alby because the extension can authorize actions without the site seeing the user's private key. That is the right default for a web app that handles streaming, chat and payments.
The code also supports private-key login and account creation. `login.ts` can use `Nip7Signer` or `PrivateKeySigner`, stores a session object in `window.localStorage`, and the signup flow can generate a new key, ask for profile details and publish profile metadata. For extension login, the site does not receive the private key. For direct private-key login, the trust model is much heavier.
Local storage is convenient, especially for a live app where a creator does not want to log in every time a dashboard refreshes. It is not a vault. Browser extensions, injected scripts, device compromise or cross-site bugs can turn local persistence into account risk. A streamer should avoid using a high-value identity with a direct private-key login unless they fully understand the tradeoff.
There is also a social-state risk. Open issue #19 says following npubs from inside zap.stream can delete follows outside zap.stream. That issue is still open in the current tracker. Follow lists are shared Nostr state, not only an app preference. Any client that edits them should be conservative, and users should keep a backup habit for important contact lists.
Videos, uploads, clips and Blossom
zap.stream is not only a live page. The app has routes and code for videos, shorts, uploads and clips. The upload path uses Blossom servers from a user's configured server list, falling back to `https://nostr.download/` when none are set. The upload service signs a Blossom auth event, uploads the blob and receives a descriptor that can become Nostr media metadata.
`v0l/route96`, the server behind nostr.download, describes itself as a Blossom and NIP-96 server. GitHub metadata checked on June 13 showed a Rust project with 25 stars, six forks, a May 28 push and topics around Blossom, NIP-96 and Nostr. This matters because live products quickly produce artifacts: thumbnails, covers, clips, recordings and uploaded videos.
Clips make the connection visible. The stream clip code can call a provider clip endpoint, then publish a live stream clip event linked back to the live activity. The app's summary chart and stream state code also knows about live chat, raids, clips, zap receipts, reactions and notes. A good live product does not end when the stream stops; it leaves objects people can reference.
Storage remains a trust boundary. Blossom and NIP-96 style servers can make media more portable, but they still have policies, costs, moderation, retention and failure modes. If a creator needs recordings for business, legal, educational or paid-access purposes, they should keep an independent archive instead of assuming every Nostr-linked media URL will stay online.
Mobile app and current build trail
The mobile trail is now explicit. The web source links the download page to Google Play package `io.nostrlabs.zap_stream_flutter`, a TestFlight invite and the `nostrlabs-io/zap-stream-flutter` repository. The Google Play listing describes zap.stream as a live-streaming app powered by Nostr where creators can stream directly to fans and keep the tips passed through from viewers.
The Flutter repository metadata checked on June 13, 2026 showed a project created on May 8, 2025, pushed on April 3, 2026, written in Dart, with 11 stars, two forks and 12 open issues. The repository description says it is the zap.stream Flutter app. That is enough to treat mobile as real, but not enough to treat it as a finished consumer platform.
The live web app's raw shell also exposed a concrete current version: `v0.5.0-109-g811e55f`. The cloned web repository's latest commit was `811e55f chore: bump pkgs`, matching that build suffix. The `package.json` shows a modern React and Vite stack, Bun workspaces, @snort system packages, @snort/wallet, hls-video-element, media-chrome, React Intl, Workbox PWA pieces and @zap.stream/api as a workspace package.
For readers, the lesson is that zap.stream is actively built, but active does not mean frictionless. Web, mobile, provider API, core backend and media storage are separate moving pieces. When something breaks, the fault may sit in the app, a relay, a provider, a mobile build, a signer, a wallet, Cloudflare, OBS settings or a media URL.
Terms, moderation and analytics
The terms page is narrow in an important way. It says the terms apply to zap.stream-provided streaming providers. That is sensible because zap.stream can publish or view Nostr live events from many places, but provider hosting is where the service has to enforce conduct, rights and access rules. The page prohibits streaming or uploading copyrighted content without rights and reserves suspension or termination for violations.
That does not contradict Nostr's open relay model. It describes the ordinary reality of media hosting. Video infrastructure has costs, legal exposure and abuse pressure. A public Nostr event can point to an HLS URL, but the server behind that URL still has to decide what it will carry, store, bill and remove.
The raw live HTML also loads Google Tag Manager. That does not automatically mean a privacy disaster, but it is relevant for a live media app. Viewers and creators should assume the hosted website has web analytics unless proven otherwise, and operators embedding streams should understand which third-party scripts are present on the page they send people to.
Moderation is especially hard in live rooms because the harm arrives before review can be leisurely. Chat, stream titles, images, raids, clips, payments and profile links can all be abused. If you run a public event, prepare moderation roles, relay choices, backup communication and recording policy before the audience arrives.
Current issue tracker signals
The public issue tracker is a useful reality check. On June 13, 2026, the `v0l/zap.stream` GitHub API showed seven open issues and one open pull request. The open items included Google Cast support, NWC relay AUTH challenge handling, follow-list overwrite behavior, deletion of past streams, widget message decay, stream chat loading improvements and chat message bleed across channels.
Some of those are feature requests, but a few are risk markers. NWC relay AUTH challenge handling matters because wallet connectivity can depend on authenticated relay sessions. Chat message bleed across channels matters because live chat must be tied to the correct room. Follow-list overwrite behavior matters because a streaming client should not damage a user's wider Nostr social graph.
The open pull request titled `fix: stream chat loading improvements` is also telling. Chat loading is not a decorative component in zap.stream. It is part of the live room. If chat loads slowly, misses messages or mixes channels, the viewer experience and moderation model suffer. Watching the issue tracker is therefore a practical way to judge product maturity.
The point is not to scold the project. Open issues are normal in real software. The point is to avoid pretending that a live-media stack is finished because the concept is exciting. Before you use zap.stream for a high-stakes stream, check the current issue list, run a rehearsal and know what failure would cost.
What to test before watching
If you are only watching, the checklist is short but worthwhile. Confirm the domain is `zap.stream`, inspect whether the stream card links to a Nostr address, check that the title and host look plausible, and see whether the stream plays without asking for unnecessary permissions. Watching should not require camera or microphone access.
If you chat, remember that live chat is public Nostr content tied to a live activity. Use the same judgment you would use for any public Nostr post. If you zap, start with a tiny amount and verify the recipient, amount, wallet prompt and event target. A live room is designed to make support feel immediate; your spending limits should still be deliberate.
Be cautious with impersonation. A stream can show a familiar name, profile image or npub-like route. That does not prove the person is who you think they are. For important fundraisers, verify the creator through another trusted channel or a known Nostr profile before sending meaningful sats.
If playback fails, do not assume Nostr failed. The relay may have delivered the event correctly while the media URL, provider, HLS playlist, DNS, browser codec, content warning, VPN or regional network path is failing. The social layer and the video layer fail in different ways.
What to test before streaming
If you are streaming, run a private rehearsal with the exact setup you will use publicly. Log in with your intended signer, choose a provider, check the provider balance, copy the Stream URL and Stream Key into OBS, use the recommended codec settings and go live long enough to test audio, video, stream delay, chat, zaps and ending behavior.
Then inspect the Nostr side. Open the stream in another browser or client and confirm that the kind 30311 event has the expected title, summary, image, status, streaming URL, topics and host tags. Send a harmless chat message and verify that it is tied to the correct live address. Send a tiny zap and confirm the receipt is connected to the intended target.
Test money paths separately. Provider balance top-ups are not the same thing as viewer zaps, and withdrawals are not the same thing as invoice generation. If you configure NWC, use a wallet connection with tight permissions and revoke it after the test if you do not need automation. Do not use a high-balance wallet for a first public stream.
Finally, plan for boring operations. Keep a backup recording if the stream matters. Have a second communication channel if chat breaks. Know how to rotate the stream key. Check that the provider terms are acceptable for your content. If you self-host, monitor CPU, bandwidth, disk and payment accounting while streaming, not after.
When zap.stream is a good fit
zap.stream is a strong fit when a Nostr-native audience wants live video with chat and sats around the event. It is especially natural for builder streams, Bitcoin and Nostr talks, community radio, live coding, music sessions, gaming, public office hours, protocol walkthroughs and creator experiments where viewers already understand npubs and zaps.
It is a weaker fit if you need enterprise meeting controls, guaranteed privacy, managed compliance, mature support contracts, private webinars with strict access controls or a stream that must survive every outage without rehearsal. Nostr identity and zaps are powerful additions, but they do not replace the operational discipline of professional streaming.
It is also not the right mental model for wallet custody. zap.stream can interact with wallets, NWC, top-ups, withdrawals and Lightning invoices, but it is not primarily where you should think about long-term fund storage. Keep streaming balances and creator support flows separate from high-value savings.
The best expectation is practical: use zap.stream when the public live moment becomes better because the event, chat, tips and identity can travel through Nostr. Use more conventional or locked-down tools when the audience, privacy, contractual or compliance requirements demand them.
The reader takeaway
zap.stream deserves a serious place in the Nostr map because it tests whether open social identity can work in a medium that is expensive, real-time and unforgiving. A text post can wait. A live video cannot. If the provider, stream key, player, relay, chat or wallet path breaks, the audience feels it immediately.
The product's strength is that it does not pretend Nostr alone solves video. It uses Nostr where Nostr is useful: identity, event addressing, chat, zaps, goals, media metadata and public discovery. It uses normal streaming infrastructure where normal streaming infrastructure is still required. That honesty makes the project worth watching.
The current caution is equally clear. Provider routes can fail, issues remain open, mobile is still young, direct key login has trust costs, NWC needs careful permissions, and media storage is not the same as permanent archiving. Those are not reasons to dismiss zap.stream. They are the conditions under which a live-media Nostr app becomes real.
If you use it, start small. Watch a stream, send a tiny zap, inspect the Nostr event, rehearse with OBS, then scale up only after the exact workflow behaves as expected. That is the right rhythm for a project that is exciting precisely because it connects so many moving parts.
Sources worth opening
Start with the live zap.stream app, FAQ, terms, manifest, GitHub repository, package metadata, @zap.stream/api package, zap-stream-core docs, mobile app repository, Google Play listing and the current issue tracker. Then compare NIP-53, NIP-57, NIP-98, NIP-47, NIP-71 and Blossom/NIP-96 media storage references before relying on any streaming or wallet behavior.
- zap.stream live app
- zap.stream FAQ
- zap.stream providers page
- zap.stream terms of service
- zap.stream download page
- zap.stream manifest
- v0l/zap.stream repository
- v0l/zap.stream API metadata
- zap.stream README
- zap.stream package.json
- zap.stream constants
- zap.stream FAQ source
- zap.stream terms source
- zap.stream download source
- zap.stream login store
- zap.stream signup source
- zap.stream wallet hook
- zap.stream SendZaps component
- zap.stream live chat source
- zap.stream chat writer source
- zap.stream stream editor source
- zap.stream stream provider hook
- zap.stream discover providers hook
- zap.stream provider selector
- zap.stream NWC config source
- zap.stream stream page
- zap.stream stream state source
- zap.stream clip button
- zap.stream summary chart
- zap.stream live streams hook
- zap.stream Blossom upload service
- zap.stream upload page
- @zap.stream/api README
- @zap.stream/api constants
- @zap.stream/api provider client
- @zap.stream/api stream utils
- v0l/zap.stream open issues
- Issue 13: NWC relay AUTH challenge
- Issue 19: follow list behavior
- Issue 60: chat message bleed
- Pull request 54: chat loading improvements
- v0l/zap-stream-core repository
- zap-stream-core API docs
- zap-stream-core admin API docs
- zap-stream-core deployment docs
- zap-stream-core variants docs
- v0l/route96 repository
- nostrlabs-io/zap-stream-flutter repository
- zap.stream on Google Play
- zap.stream TestFlight invite
- zap.stream on NostrApps
- Shosho docs for Zap Stream Server
- NIP-01 basic protocol flow
- NIP-07 window.nostr capability
- NIP-47 Nostr Wallet Connect
- NIP-53 live activities
- NIP-57 Lightning zaps
- NIP-71 video events
- NIP-94 file metadata
- NIP-96 HTTP file storage
- Blossom specification





