AGORA.GRIPE
Lightningalphav0.0.10

Thunder Bridge

Route Lightning sat to any wallet. Interactive demo of the Thunder Bridge npm package.

// gateway
ALPHAv0.0.10

Age-gating financial rails kills innovation and stifles creativity for everyone locked out. So here comes Thunder Bridge.

Thunder Bridge is a thin wrapper on top of a Lightning node. A few lines of code and your app starts taking sat straight into your own LN wallet. Hook anything you want onto every donation.

// problem

You've got an idea and you know it'll need to take sound money. Now let's run through who the standard payment rails kick out on day one. Under 18? Stripe, PayPal and your bank send you home. Anything in a vertical the regulator doesn't currently like? Account terminated. Live in a country that happens to be on the wrong list this week? Cheers, take care. "Consumer protection," "destination principle," "level playing field," "fair taxation of the digital economy," "preventing market distortion," the regulators call it, but what they're mostly protecting you from is earning your own money. Cool, thanks.

// approach

Spinning up a Lightning node for the occasion, playing treasurer, babysitting channels and liquidity? Probably not either. First you want to find out if the thing has any pulse, and for that you need the simplest possible end-to-end path so it actually runs. Complications show up on their own, once they're really needed.

// goal

Thunder Bridge is that shortcut, but the goal goes further: cut the barrier to entry to zero and get it to a place where the gateway itself has no technical way to control or block anything. The goal is to have it by design, not by policy: sat in, sat out. No paperwork, no age gate, no "sorry, kid", no "not that country". Part of that vision is multiple independent hosts, so the payment does not stand or fall with one node or one person.

A technically savvy person can already pull this off today via Breez SDK, phoenixd, their own BTCPay Server, ... The point of this project is to open the same door to people who aren't quite that technical, who only need a one-off or stop-gap solution, or who simply prefer simplicity. Just bring an idea and a few lines of code (or an agent that writes them for you).

01

Routing

Sat from a Lightning address land straight in your wallet. No node required.

02

Triggers

Webhook and WebSocket event on every payment. Drive whatever.

03

Programmatic

A few lines of JS. Runs in browsers, Node, Bun, and edge runtimes.

What you can build

// use cases

Stream alerts

Live overlay on every donation for Twitch, YouTube, or OBS. Trigger plus streamTrigger over WebSocket deliver events in real time.

createTrigger + streamTrigger

IoT triggers

Light a lamp, open a door, drive a vending machine. Your ESP or Pi connects over WebSocket and the hardware reacts to every payment.

createTrigger + streamTrigger

Pay-per-use API

Unlock an API key, an AI generation, or a file. Donation confirmed by webhook equals access granted.

createDonation + webhook

Tip jar widget

Drop a donate form on your blog. createDonation renders the QR, waitForFulfillment shows status live.

createDonation + waitForFulfillment

Game server triggers

Minecraft, Counter-Strike: send sats = kill a random player, drop loot, summon a mob, change the weather. Lightning-funded chaos for your server.

createTrigger + streamTrigger

Anti-spam paywall

Send 1 sat to comment, submit a form, or hit an API. Bot economics collapse, humans barely notice, no captchas.

createDonation + waitForFulfillment
// roadmapthunder-bridge@0.0.10

This is alpha. The vision is clean programmatic access, no fluff. The gateway is automated, but you still have to trust the proxy will pay out. If it catches on and there is real demand, we might get to BOLT12 offers and blinded paths for trust-minimized routing, open the source, and prep it for self-hosting. 🧡

Alpha
BOLT12 + blinded paths
Beta
Open-source / self-host
// sandbox

Try the API

Eight short examples that walk you through the API. Each card shows real code on the left and a live preview on the right. Run them in order, or jump to the part you need.

step 01
1

QR code from any Lightning destination

`invoiceToSvg` returns a deterministic SVG string for BOLT11 invoices, BOLT12 offers, and LN addresses (LUD-17). Encoded with the `LIGHTNING:` URI scheme and uppercased for QR alphanumeric compression and wallet compatibility. Pure client-side. No canvas, no network call.

code
import { invoiceToSvg } from "thunder-bridge";

// Works for BOLT11, BOLT12, and LN addresses (LUD-17).
// Encodes with the LIGHTNING: URI scheme + uppercase
// for wallet compatibility and QR alphanumeric compression.
const svg = invoiceToSvg("alice@getalby.com", {
  size: 220,
  color: "#1a1a2e",
});

document.body.innerHTML = svg;
step 02
2

Naive type detection

Quick format check that tells Lightning addresses apart from BOLT12 offers. Just a regex over the input. No network call, no domain lookup, no signature check.

code
import { detectDestinationType } from "thunder-bridge";

detectDestinationType("alice@getalby.com");
// "lnAddress"
LN address
inputalice@getalby.com
detected typelnAddress

Useful for client-side validation before you call createDonation. Always re-validate on the server.

step 03
3

Estimate fees

Ask the gateway how many sat will reach the recipient before you create a donation.

code
import { ThunderBridge } from "thunder-bridge";

const tb = new ThunderBridge("https://thunder-bridge.agora.gripe");

const fees = await tb.estimateFees(1000);

console.log(fees);
// Press Run to fetch the live breakdown.
Click Run to fetch a fee estimate from the gateway.
step 04
4

Create a donation

Generate a BOLT11 invoice that pays out to a Lightning address. Scan it with any wallet.

code
import { ThunderBridge } from "thunder-bridge";

const tb = new ThunderBridge("https://thunder-bridge.agora.gripe");

const { id, bolt11, expiresAt } = await tb.createDonation({
  destination: "alice@getalby.com",
  amountSat: 21,
});

// Render the bolt11 invoice as a QR code
// (your wallet scans it and pays)

The invoice is real. Scanning it triggers an actual Lightning payment.

step 05
5

Track payment in real time

Opens a WebSocket to the gateway and subscribes to status events for one donationId. `onStatusChange` fires on every transition through `invoice_created → payment_received → paying_out`. Resolves with the terminal state (`success | failed | expired`); rejects when `timeoutMs` runs out.

code
import { ThunderBridge } from "thunder-bridge";

const tb = new ThunderBridge("https://thunder-bridge.agora.gripe");

const finalStatus = await tb.waitForFulfillment(donationId, {
  onStatusChange(status) {
    console.log("status:", status);
    // "invoice_created" -> "payment_received"
    //   -> "paying_out" -> "success"
  },
  timeoutMs: 600_000,
});

console.log(finalStatus); // "success" | "failed" | "expired"
Create a donation in step 4 to track it here.
step 06
6

Create a trigger

A trigger is a reusable Lightning address with a fixed price. Share the QR, donations stream into your app.

code
import { ThunderBridge } from "thunder-bridge";

const tb = new ThunderBridge("https://thunder-bridge.agora.gripe");

const trigger = await tb.createTrigger({
  priceSat: 21,
});

console.log(trigger.ln_address);
// "ln-XXXXX@thunder-bridge.agora.gripe"
console.log(trigger.hash);
// share this hash with streamTrigger
step 07
7

Stream donations to your app

Open a WebSocket and react to every donation as it lands. Replays history on connect, auto-reconnects. Raw URL is `wss://thunder-bridge.agora.gripe/ws/triggers/'<hash>'`, so you can verify it in any generic WS client (e.g. websocketking.com). From that stream you can drive whatever: a Slack or Discord alert, an LED blinking on an ESP32, a door opener, a donation overlay in your livestream, an in-game event, a push notification, a database write, basically anything that listens.

code
import { ThunderBridge } from "thunder-bridge";

const tb = new ThunderBridge("https://thunder-bridge.agora.gripe");

const stop = tb.streamTrigger(triggerHash, {
  onDonation(d) {
    console.log("+" + d.amount_sat + " sat");
    // Drive your IoT device, alert, counter...
  },
  onConnect: () => console.log("WS open"),
  onDisconnect: () => console.log("reconnecting"),
});

// Later: stop the stream
// stop();
Create a trigger in step 6 to stream its donations here.
step 08
8

Verify a webhook

Receive POST notifications on your own server with HMAC-SHA256 signatures you can trust.

code
// app/api/webhook/route.ts (Next.js App Router)
import { parseWebhookRequest } from "thunder-bridge";

export async function POST(req: Request) {
  const payload = await parseWebhookRequest(
    req,
    process.env.WEBHOOK_SECRET!,
  );

  // Returns null if X-Signature-256 is invalid
  if (!payload) {
    return new Response("Bad signature", { status: 401 });
  }

  console.log(payload.event); // "donation.success"
  console.log(payload.donation.amount_received_sat);

  return new Response("OK");
}
Server-only. Drop this into your route handler.
parseWebhookRequest verifies the X-Signature-256 header. Returns null on bad signature.
Retries on failure: 10s, 1m, 2m, 5m, 10m, 30m, 1h, then hourly up to 1 week.
Sample verified payload
{
  "event": "donation.success",
  "signal_only": false,
  "donation": {
    "id": "d_a1b2c3...",
    "destination": "alice@getalby.com",
    "amount_received_sat": 1000,
    "amount_sent_sat": 995,
    "network_fee_sat": 5,
    "status": "success",
    "error_message": null,
    "created_at": "2026-04-25T14:32:01Z",
    "updated_at": "2026-04-25T14:32:08Z"
  }
}

// guide

Use it in your project

Install the Thunder Bridge npm package and start accepting Lightning donations in a few lines of code. Works in Node.js, Bun, Deno, browsers, and edge runtimes.

Install

bash
npm install thunder-bridge

Claude Code skill

If you build with Claude Code, the npm package ships a skill that teaches Claude the current API and integration patterns. Install it into your repo and Claude picks it up automatically when you write Thunder Bridge code.

bash
# Per project (./.claude/skills/)
npx thunder-bridge install-skill

# Global for your user (~/.claude/skills/)
npx thunder-bridge install-skill --global

# Overwrite existing copy
npx thunder-bridge install-skill --force