Inspiration
In modern web development, we are told that to build a functional app, we need cloud hosting, managed databases, tracking telemetry, and strict user authentication workflows.
ZapQR was born out of a desire to break this paradigm and honor the original cypherpunk vision of the web: a decentralized, permissionless ecosystem where tools are purely utility-driven, self-custodied, and trustless. We want to see if we could build a full-featured Bitcoin Lightning payment utility that requires no server, no database, no accounts, and zero logs.
What it does
ZapQR is a static, browser-native utility designed to bridge the Nostr social protocol and the Bitcoin Lightning Network. It is a lightweight, peer-to-peer portal for receiving and managing microtransactions.
How we built it
Frontend: Built using raw TypeScript.
Nostr Integration: Utilized Nostr client protocols to handle key cryptographic signing, event parsing (Kind 9734 for Zap Requests, Kind 9735 for Zap Receipts), and real-time WebSockets to talk directly to decentralized relays.
Lightning Connectivity: Integrated LNURL-pay protocols to securely interact with the user's Lightning address and generate dynamic invoices completely on the client side.
Cryptography: Handled key derivation and local storage management using standard web crypto APIs.
Challenges we ran into
Storing the private key (nsec) locally means relying on localStorage, which is inherently vulnerable to Cross-Site Scripting (XSS). Balancing absolute security with user convenience forced us to think deeply about security boundaries and how to transition toward external extension isolation (like Alby or Nos2x).
Asynchronous Relay Racing: Nostr relays are decentralized, meaning they don't guarantee uptime or synchronous data delivery. We had to implement aggressive local caching and robust query-retry logic to aggregate payment history from multiple scattered sources seamlessly without losing transaction details.
Client-Side Invoice Synthesis: Without a backend server to act as a proxy, fetching LNURL-pay endpoints frequently triggered CORS (Cross-Origin Resource Sharing) restrictions, requiring creative client-side handling to bridge the browser to external Lightning providers smoothly.
Accomplishments that we're proud of
We completely eliminated the database. There is no infrastructure for an attacker to breach, no logs to subpoena, and no tracking cookies to block.
What we learned
The modern web sandbox is surprisingly powerful enough to build autonomous financial primitives—if you're willing to re-architect how data flows. Relying on open cryptographic protocols like Nostr eliminates the need for proprietary database schemas.
What's next for ZapQR
PWA: Packaging ZapQR as a Progressive Web App (PWA).NIP-07 & Extension Native Isolation: Transitioning away from browser localStorage by implementing native NIP-07 browser extension support, allowing users to keep their nsec entirely isolated within dedicated wallets.BOLT12 & NWC Integration: Removing our reliance on external third-party LNURL-pay servers by integrating native Nostr Wallet Connect (NWC) and BOLT12 static offers. This will allow the static HTML file to talk directly to a user's self-custodied Lightning node over Nostr relays, finalizing the loop of pure end-to-end decentralization.
Log in or sign up for Devpost to join the conversation.