Sparrow is a serverless, peer-to-peer photo and video sharing app built by Algoramming. Your phone becomes a live host and the people you invite connect directly, so photos and videos stream device to device over encrypted WebRTC, never uploaded, never stored in the cloud.

Every mainstream sharing app uploads your photos to a company server, where they sit stored, indexed, and retained on terms you never wrote. Big albums mean waiting on an upload then a download, free tiers fill up, links expire, and quality gets crushed. Sharing a moment should not mean filing it into a locker.
Sparrow turns your phone into a live host. Invited viewers connect to it over WebRTC, and media streams device to device through an encrypted data channel. Supabase Realtime carries only the signaling text that introduces two phones, while STUN and a self-hosted TURN relay bridge different networks and countries.
People share moments live, with a real-time viewer count, without a file touching a server. A compressed manifest, then thumbnails, then full files on tap keep a thousand-photo album feeling instant. Sessions stay private, hosting runs in the background like a call, and closing the app leaves nothing in a cloud.
Short answer: Algoramming built Sparrow, a live peer-to-peer photo and video sharing app that lets people share their moments without uploading a single file to a server. When you start a session, your phone becomes a live host, and the people you invite connect to it like a phone call. Photos and videos stream device to device over an encrypted WebRTC data channel, and nothing is ever stored in a cloud. Close the app and the sharing stops. Sparrow is a cross-platform Flutter app on Supabase and Firebase, it moves a library of a thousand photos across two different networks in two different countries almost instantly, and it carries no ads, no in-app purchases, and no tracking. Its tagline says it plainly: share the moment, not the upload.
Sharing a set of photos should be the easy part, and yet the tools most people reach for all work the same way. You pick your photos, they upload to someone else's server, they sit there, and the other person downloads a copy. That single design decision carries a long tail of problems.
Your private moments now live on a company's storage, indexed and retained on terms you did not write and cannot see. Sharing a large event album means paying for the round trip twice, once to upload and once to download, and the wait grows with the size of the album. Free storage tiers fill up, shared links quietly expire, and image quality gets crushed by a second round of compression the moment a file is re-encoded for delivery. For a grandparent abroad who just wants to watch a new baby's first week unfold, the whole ceremony of upload, link, wait, and download gets in the way of the moment itself.
There is a quieter cost too. Once a photo is on a server, you have lost control of its lifetime. Deleting the copy on your phone does nothing to the copy in the cloud, and revoking a link rarely means the file is gone. The people who care most about this, families sending pictures of children and friends sharing a private evening, are exactly the people served worst by the upload-and-store model.
We wanted to build something that felt less like filing photos into a locker and more like opening a window between two phones. The requirements were direct:
The word serverless deserves a straight explanation, because Sparrow does use a backend, just not for your photos. Think of it as the difference between a switchboard and a warehouse. Older sharing apps are warehouses: your files go in, they stay there, and other people come to collect a copy. Sparrow is a switchboard: our backend only introduces two phones and then steps out of the way. Once the two devices are talking, every photo and every video travels straight between them, over a private connection the server is not part of.
That inversion changes the whole shape of the product. There is no bucket of your images to secure, because there is no bucket. There is no storage bill that grows with every session, because nothing is stored. There is no shared link to leak, because access lives in a live session that ends when you close the app. The privacy story stops being a policy you have to trust and becomes a property of how the app is built.
| Capability | What it does |
|---|---|
| Live sessions | Pick photos and videos, start a session, and host them in real time with a live viewer count |
| Serverless transport | Media streams device to device over an encrypted WebRTC data channel, never uploaded or stored |
| Public or private | Private sessions are invite-only, public sessions let anyone join with a four-digit code |
| Circles | Reusable, avatar-backed groups so you can invite a whole family or friend group in one tap |
| On-demand streaming | A compressed manifest and thumbnails load first, and full-resolution files only when tapped |
| Save what you receive | Viewers can save received photos straight to their own gallery |
| Background hosting | The session keeps running when the app is backgrounded, like an ongoing call |
| Cross-network reach | STUN and a self-hosted TURN relay connect two phones across different networks and countries |
The direct link between two phones is built on WebRTC, the same real-time technology behind video calls in the browser. WebRTC was designed to move live audio and video between two people with the lowest possible delay, and Sparrow uses its data channel, the same pipe repurposed to carry photos and videos instead of a call.
When a viewer joins your session, the two devices have to agree on how to talk before any media can move. They exchange a short technical handshake, an offer from the host and an answer from the viewer, each describing what the device supports, along with a list of possible network routes to reach each other. Sparrow carries these small text messages over Supabase Realtime broadcast channels, one channel per session. Once the handshake completes, a private, DTLS-encrypted data channel opens directly between the two phones, and the media flows through it. The backend never sees a single image, only the handful of text messages that set up the call.
The hard part of any peer-to-peer app is that most devices are not directly reachable. Home routers, mobile carriers, and office firewalls all hide phones behind NAT, network address translation, so a phone in one country has no public address another phone can simply dial. Solving this reliably is where a lot of well-meaning peer-to-peer projects quietly fall apart, and it is where Sparrow puts real effort.
Sparrow handles it the way video calls do, with ICE, STUN, and TURN. ICE, interactive connectivity establishment, is the process of gathering every possible route between two devices and then testing them to find one that works. STUN is a lightweight helper that lets each phone discover its own public address as the internet sees it, which is enough for most connections to punch straight through and go device to device. When a network is too restrictive for any direct route, a self-hosted TURN relay steps in and forwards the connection so the session still succeeds. Crucially, the relay only ever passes along encrypted packets it cannot read, so even the fallback path keeps your media private.
Signaling itself has a subtle problem worth naming. Supabase Realtime broadcast is fast but best-effort, which means an individual message can be dropped, and a WebRTC offer can be several thousand characters long. Sparrow handles both. Large offers are split into fragments, sent across several broadcast messages, and reassembled on the far side, and the whole exchange is retried a few times if an answer does not come back. Early network candidates that arrive before the connection is ready are queued rather than discarded. These are small details, but together they are the difference between a session that connects on the first try and one that spins.
Sparrow is written in Flutter and Dart from a single codebase, and it follows a feature-first modular structure. Each feature, from authentication to sessions to circles to notifications, is its own slice with its own API, model, provider, view, and service layers. Cross-cutting concerns like configuration, the database, theming, logging, and shared widgets live in a core layer that every feature can lean on. Across the app that adds up to a couple of hundred well-organized Dart files rather than one tangled pile, which keeps each feature readable on its own and safe to change without disturbing the rest.
State is managed with Riverpod, navigation runs on go_router with an authentication guard and a maintenance-mode redirect, and dependencies are wired through the get_it service locator so platform info, the app directory, settings, and the Supabase client are all resolved in one place. Local preferences and cached data sit in Hive, a fast on-device store, so the app opens straight into a usable state without waiting on the network.
The backend is Supabase. Postgres holds the accounts, circles, sessions, notifications, and per-device push tokens, and every table is locked down with Row Level Security so a person can only ever read the rows that belong to them or that were shared with them. Supabase Realtime carries both the presence signals, which tell a viewer whether a host is genuinely online right now, and the WebRTC signaling messages. Two Edge Functions written in TypeScript round it out: one fans out push notifications when an invite arrives, looking up the receivers' device tokens and pruning dead ones as it goes, and one handles full account deletion. Push delivery itself runs on Firebase Cloud Messaging.
A live album is not one file, it is often hundreds or thousands of them, and a naive approach would either flood the connection or run the phone out of memory. This is where the most interesting engineering in Sparrow lives, and it is worth walking through.
When a viewer joins, the host does not send any images. It first sends a compact, gzip-compressed manifest, a lightweight list describing every item in the album. The viewer's screen fills with placeholders immediately. As the viewer scrolls, the app requests only the thumbnails for the photos currently on screen, and only when a photo is actually tapped does it ask for the full-resolution file. Nothing is transferred until it is about to be seen. That is why an album of a thousand photos feels instant: at any moment, the connection is only carrying the handful of images in front of the viewer.
Under that behavior sits a small binary protocol we wrote for the data channel, because a single connection has to carry many things at once. A grid of thumbnail requests, a control message, and the occasional full-resolution download all share the same pipe, and they cannot be allowed to get tangled. Sparrow solves this by tagging every binary frame with a short transfer-id header, a few bytes at the front that say which transfer this chunk belongs to. That lets dozens of transfers interleave down one channel and be reassembled correctly on the other end, so a screen full of thumbnails all load together without corrupting each other.
The rest of the protocol is about staying polite on a shared pipe. Files move in 16 KB chunks, and the host watches the channel's outgoing buffer so a fast sender never overwhelms a slower viewer, pausing when the buffer runs high and resuming when it drains. Each viewer gets its own isolated request queue, so one person tapping quickly through photos never stalls anyone else in the session. On the receiving side, a thumbnail cache and a cap on how many images fetch at once keep scrolling smooth no matter how large the album is. None of this is visible to the person using the app, which is the point. The complexity lives in the engine so the experience stays simple.
Peer-to-peer is unforgiving in the real world, where networks drop, people switch from Wi-Fi to mobile data mid-session, and the same person signs in on two devices. A lot of the work in Sparrow went into making the connection feel reliable anyway.
People move. Someone hosting from their kitchen walks out the door, and their phone hands off from Wi-Fi to mobile data, which changes its address entirely. Left alone, WebRTC would take twenty or thirty seconds to notice the old route is dead before it gives up and reconnects, and to a viewer that looks like the session has frozen. Sparrow watches for these changes directly. The moment the host's network shifts, the app rebinds its real-time connection on the new interface and signals every viewer to reconnect right away, so a session recovers in a moment instead of appearing to stall.
A viewer should never open a session whose host has already walked away. Sparrow leans on real-time presence so a session only becomes joinable when its host is verifiably online at that instant. If the host closes the app, presence drops, and the session stops being something anyone can join. It matches the mental model of a call: there is no voicemail, because there is no server holding your photos to hand out later.
Plenty of people are signed in on both a phone and a tablet. Sparrow gives every device its own signaling identity, kept separate from the account it belongs to, so a second device can even join a session that the first device is hosting, as an ordinary viewer. The hosting controls, the live status chip and the stop button, only ever appear on the device that is actually hosting, so there is never a question of which screen is in charge.
When a peer-to-peer connection does fail, most apps show a spinner and then a shrug. Sparrow keeps detailed diagnostics through the whole handshake, tracking whether the viewer joined the room, whether the host was present, whether the offer and answer were exchanged, and which kinds of network routes were found. When something goes wrong, it turns that record into a plain-language explanation the person can actually act on, rather than a generic error. That same diagnostic trail is what makes hard connectivity problems debuggable in the field instead of a guessing game.
The design choices all come back to one idea: sharing should feel live, and it should feel private.
Privacy in Sparrow is not a setting bolted on at the end, it falls out of the architecture. Because the media never touches a server, there is no stored copy to breach, subpoena, or accidentally leave public. The data channel between two phones is DTLS-encrypted, so the photos are protected in transit even on the fallback relay path, which forwards packets it has no key to read. Sparrow keeps this posture consistent all the way down: every Supabase table is guarded by Row Level Security, so the database will not return a row to anyone it does not belong to, and the app ships with no ads, no in-app purchases, and no third-party tracking. When you close a session, there is nothing left behind to clean up, because there was never anything stored in the first place.
Sparrow has just launched and is in active development. The core is live: peer-to-peer sessions, public and private sharing, circles, on-demand streaming of large libraries, background hosting on Android and iOS, and cross-network connectivity through self-hosted relays. It is a Flutter codebase that targets Android, iOS, web, macOS, Windows, and Linux, ships in English and Bengali, and carries no ads, no in-app purchases, and no tracking. The roadmap ahead includes saving received videos to the gallery, further connection tuning across difficult networks, and continued hardening of the real-time engine as more people share on it.
You can see Sparrow and how it works at sparrow.algoramming.com, and get the app from the Sparrow download page.
Framework: Flutter and Dart, one codebase for Android, iOS, web, macOS, Windows, and Linux. Real-time media: flutter_webrtc for a direct, encrypted data channel between devices, with STUN for discovery and a self-hosted coturn TURN relay for strict networks. Backend: Supabase, with Postgres and Row Level Security for accounts, circles, sessions, notifications, and device tokens, Realtime for presence and WebRTC signaling, Storage for avatars, and Edge Functions for push fan-out and account deletion. Push notifications: Firebase Cloud Messaging, with flutter_local_notifications for on-device display. State, navigation, and DI: Riverpod for state, go_router for routing with auth and maintenance guards, and get_it for dependency injection. Local storage: Hive for fast on-device preferences and cached data. Media handling: photo_manager, image_picker, image_cropper, video_player, and chewie for browsing, picking, and playing photos and videos. Native background: an Android foreground service and an iOS Live Activity with Dynamic Island support, bridged over a platform channel, to keep hosting alive.
Sparrow is a serverless, peer-to-peer photo and video sharing app. When you start a session, your phone becomes a live host, and the people you invite connect to it directly. Your photos and videos stream device to device over an encrypted WebRTC data channel, and nothing is ever uploaded to or stored on a server.
Sparrow uses WebRTC, the same real-time technology behind video calls, to open a direct, encrypted connection between two phones. The backend only helps the two devices find each other, then steps out of the way. The media travels straight between the devices, so there is no upload and no cloud copy.
Yes. Sparrow uses ICE, STUN, and a self-hosted TURN relay to connect two phones even when they are on different networks in different countries and hidden behind strict firewalls or mobile carriers. When it has to use the relay, it only forwards encrypted packets it cannot read.
Yes. The host first sends a small compressed manifest of the whole album, then thumbnails as the viewer scrolls, and the full-resolution file only when a photo is tapped. Because nothing loads before it is needed, an album of a thousand or more photos feels instant.
Sharing stops. Because there is no server storing your media, closing the app ends the session and there is nothing left behind in a cloud. It works like a call: when you hang up, it is over.
Yes. Sessions are invite-only by default, and a public session still requires a four-digit join code. The media is DTLS-encrypted in transit, it is never stored on a server, every database row is protected by Row Level Security, and the app carries no ads and no tracking.
Sparrow is built with Flutter from a single codebase and targets Android, iOS, web, macOS, Windows, and Linux, with live hosting focused on mobile. It ships in English and Bengali. You can download it from the Sparrow download page.
Head to sparrow.algoramming.com/download to get the app, or visit sparrow.algoramming.com to learn more about how peer-to-peer sharing works first.
Flutter and Dart on the front end, flutter_webrtc for the peer-to-peer data channel, Supabase for accounts, presence, signaling and push fan-out, Firebase Cloud Messaging for notifications, and STUN with a self-hosted coturn TURN server for network traversal.
Try Sparrow for yourself at sparrow.algoramming.com, or download the app. Want something like this built for your idea? Get in touch with Algoramming.
01 · RelatedHow we built the AI-native CMS behind algoramming.com, a Next.js 16 and Supabase platform that researches, writes, illustrates and publishes long-form SEO articles to four social networks every night, with a human in control by choice.
Read case studyWe will reply in plain English within one business day, NDA on request. Discovery call is free.
FeaturedAlgonize is the cloud ERP, CRM and POS platform built in Dhaka for multi-branch retail shops, restaurants and delivery businesses. This case study shows how one real-time dashboard unifies sales, inventory, riders, loyalty and accounting across Android, iOS, macOS and the web.
Read case study