One script tag, and a charity can take donations
There is a working demo you can donate through
The demo runs two organisations side by side and walks the whole flow through to a receipt. It is not deployed with this site: ask and we will show you.
Small organisations get quoted platform fees, a rebuild, or both, just to accept a donation. We wanted to see how small the thing could be if Stripe handled the payment and the widget only did the part the donor sees. It is a prototype. You can try it on the demo page.
One script tag names the organisation and the campaign. Everything else loads from the campaign record, so amounts can change without the host site editing anything
Rendered into a shadow root, so the host site's CSS cannot break the form and the form's styles cannot leak out. Tested against a page written to destroy it
Card details are entered on Stripe's own page. They never touch the host site or our servers, which keeps both parties out of PCI scope
The browser says what was given. The server decides what is charged. Currency and fees are worked out server side, so a tampered request cannot change the amount
A donation is only marked paid by Stripe's signed webhook, never by the donor landing on the thank-you page. That is just a redirect, and anyone can type the URL
Fee cover is a gross-up, not a surcharge. Adding the percentage on top still leaves the charity short, because the fee then applies to the larger total
Vanilla TypeScript, 5.4 KB gzipped. A React build would have started near forty, and a guest script that big gets removed by whoever maintains the host site



A charity can be taking donations from one line of HTML, with no rebuild and no developer
The same bundle serves every organisation, each with its own branding, amounts and campaigns
One-time and monthly giving from a single flow, with no product catalogue to maintain behind it
Keyboard operable and screen-reader tested: real radio inputs, errors announced and focused, and a modal that traps focus and gives it back
Tested against a host page written to break it, and against a request from an origin not allowed to embed the campaign