DEV Community

Cover image for We built a white-label P2P money app on send21: here's how to rebrand it with one file
send21
send21

Posted on

We built a white-label P2P money app on send21: here's how to rebrand it with one file

Disclosure: this is written by the team behind send21, and dewby is built on send21.

dewby is a small P2P money app for paying friends back. It's a testnet demo: test money on test networks, nothing in it has value. It's a white-label version of our open-source example app, send21 pair: the same payments engine with its own name, logo, colors and UI. And the whole brand lives in one file.

What it does

Friends connect once by scanning a code. Then there are three things to do:

  1. Pay back. Ask a friend for 120 in your own currency, or pay them. They get a request with the amount, a note and an Open wallet button.
  2. Split. Pick two or more friends, enter the total, and everyone gets their share as a separate request.
  3. QR anyone can pay. Show a QR for an amount. Whoever scans it pays from their own wallet, with no app and no account.

Each payment goes straight to the receiver's own wallet address. The payer signs in their own wallet. send21 never holds keys or funds, never signs and never broadcasts, and neither does dewby.

You can try it alone: tap Try it alone with a demo friend, send the prefilled request, tap Let Demo friend pay, and watch it go from waiting to paid. On desktop, the app sits in a phone frame next to a QR code you can scan to open it on your phone.

How it works

Every request is a send21 draft: payment instructions for one amount, asset and network, addressed to the receiver. Four details carry most of the safety:

  • The receiver address is fixed on the server. The client sends who to ask and how much. The server creates the draft with the receiver's saved address, and fails if the draft comes back with a different one. A tampered client can't change where the money goes.
  • V2 signed webhooks. send21 reports status (draft.seen, draft.confirmed, …) by webhook. dewby verifies the x-send21-signature-v2 header: an HMAC over the timestamp, the delivery id and the raw body. It turns off the legacy body-only signature and refuses deliveries more than five minutes old, so an old delivery can't be replayed.
  • Its own dedupe, on top of send21's. dewby stores each delivery id in the same transaction as the status change, so a repeated delivery is a no-op and can't confirm twice.
  • A check against the stored request. On draft.confirmed, dewby compares the asset, network and amount with what it stored when it created the request. If anything differs, the request goes to review instead of Paid.

The app is a vanilla PWA: no framework, no build step, a service worker and Web Push.

Three modes

  • mock: no key and no network. It runs on a local server, or fully in the browser like the GitHub Pages demo, where links and QR codes carry the data between phones.
  • demo: real testnet drafts from send21's public demo API, with status checked by polling.
  • api: your own scoped send21 key and webhooks. send21 accounts use live networks, so this mode refuses to start unless you set APP_ALLOW_LIVE=1.

Rebrand it with one file

Everything brand-specific is in web/brand.js:

window.BRAND = {
  name: "dewby",                 // UI name and wallet memo prefix
  tagline: "Pay friends back. Fresh.",
  storagePrefix: "dewby",        // keeps two apps on one origin apart
  siteUrl: "https://…/dewby/",   // share card URLs
  poweredBy: true,               // a small "powered by send21" line in Settings
  light: { bg, surface, ink, mint, lime, sea, pop, link, ok, warn, bad },
  dark: { … },
  forcedDark: { … },             // palette for browsers that force dark mode
};
Enter fullscreen mode Exit fullscreen mode

theme.js turns the palette into CSS variables before first paint, so the stylesheet never hard-codes a brand color. The server reads the same file, so the memo in the payer's wallet shows your app's name. To rebrand:

  1. Edit web/brand.js and swap web/icons/mark.svg.
  2. Run npm run brand. It rewrites the manifest, title, theme color and share-card meta, and redraws the icons from your mark.
  3. Run npm test. It checks every text color for WCAG AA contrast, that the manifest and HTML match the brand file, the share card size, and that no stray send21 branding is left in the UI.

The lesson: keep the brand as data, and let tests check what's easy to forget when you rebrand, like contrast, storage keys and leftover strings.

Honest limits

  • Testnet only. The demo uses Solana Devnet and Base Sepolia with test tokens. Nothing has value.
  • A prototype. It's an example to read and fork, not a product.
  • One extra tap on phones. A notification can open a web page but not a wallet, so the payer taps Open wallet to sign.

Try the demo friend, then open brand.js and change the colors. Questions or ideas: info@send21.io.

Top comments (0)