How Tip works
Tip is the tip jar built into the web apps operated by Bellissimo, Inc., dba Tip. This page covers both sides of it: leaving a tip, and how the box is added to one of our apps. Tip serves only apps we operate — it is not a public platform and there is nothing to sign up for.
Leaving a tip
- Pick an amount — the preset tiers, or Other amount for anything from $1 to $500.
- Choose One-time or Monthly.
- The box shows the exact charge and the exact statement line, then Continue opens Stripe's secure checkout — card, Apple Pay, Google Pay, or Cash App Pay, depending on your device. Card details never touch our servers.
- Stripe emails your receipt. That is the end of it, unless you chose monthly.
What appears on your statement
Card charges show the TIP prefix plus the app you
tipped, for example TIP* APP1.COM or TIP* APP345.COM.
The box shows you this string before you pay. If a charge ever looks unfamiliar,
email sent.tip.web.app@gmail.com before disputing it — we refund faster than your bank can.
Monthly tips
A monthly tip charges the same amount each month until you cancel. You can cancel at any time from the subscription portal — enter your email, no account needed — or by emailing sent.tip.web.app@gmail.com. Cancellation stops all future charges immediately.
The Venmo button
The blue venmo button is a direct link to our Venmo business
profile with the amount and app name prefilled. It is not processed by Stripe:
the charge appears as VENMO on your statement, you get Venmo's
receipt rather than ours, and a refund is arranged by email.
Refunds
Any tip is refundable on request, for any reason, within 60 days — see the refund policy.
Adding the tip box to an app
For our own apps. An app must be registered with the Tip service first — the service refuses requests from origins it does not recognize, so pasting the snippet on an unregistered site renders nothing.
The embed
One line, placed where someone finishes reading:
<script src="https://sent-tip.web.app/widget.js" data-site="your-app.com" async></script>
With no data-mount, the box renders exactly where the tag sits.
Everything renders inside a shadow root: the app's CSS cannot break the box, and
the box cannot leak styles into the app.
Every attribute
<div id="support"></div>
<script
src="https://sent-tip.web.app/widget.js"
data-site="your-app.com"
data-mount="#support"
data-theme="auto"
data-accent="#0f766e"
data-kicker="Was this useful?"
data-heading="Support this app"
data-blurb="If you'd like to support this free app, send a tip below:"
async></script>
| Attribute | Required | What it does |
|---|---|---|
data-site | yes | Registry id of the app. Everything else is optional. |
data-mount | no | CSS selector for the container; omit to render in place. |
data-theme | no | auto (default), light, or dark. |
data-accent | no | Any CSS color; the whole box recolors from it. |
data-kicker | no | Hook line above the heading. |
data-heading | no | Overrides "Support <name>". |
data-blurb | no | Overrides the line under the heading. |
data-endpoint | no | Only when serving the widget from a different origin. |
Prices, tiers, copy, the Venmo handle, and the statement descriptor are deliberately not attributes. They live in the server-side registry — one entry per app — so changing a price never means editing app pages.
Theming
Custom properties cross the shadow boundary from any ancestor:
:root {
--tip-accent: #0f766e; /* one variable recolors the whole box */
--tip-radius: 14px;
--tip-max-width: 44rem;
}
Also available: --tip-fg, --tip-muted,
--tip-surface, --tip-raised, --tip-border,
--tip-font, --tip-danger, --tip-reserve.
Dark mode is automatic.
Single-page apps
Auto-mount runs on DOMContentLoaded, before a framework renders.
Omit data-site and mount manually instead:
<script src="https://sent-tip.web.app/widget.js" async></script>
<script>
// After your framework has rendered the container:
window.Tip.mount('#support', {
site: 'your-app.com',
endpoint: 'https://sent-tip.web.app',
});
</script>
Content-Security-Policy
Apps with a strict CSP need two grants. Nothing else: the box injects no
third-party scripts, sets no cookies, and applies its styles via constructed
stylesheets, so style-src 'self' can stay.
script-src 'self' https://sent-tip.web.app
connect-src 'self' https://sent-tip.web.app
If nothing appears
The box deliberately renders nothing when its configuration request fails — a
broken box is worse than no box. The browser console says why, prefixed
[tip]:
| Console message | Cause |
|---|---|
config request failed (404) | The app is not registered. |
config request failed (403) | The page's origin is not on that app's allowlist. |
no element matches "#support" | The data-mount selector found nothing. |
| Renders, but Continue does nothing | The service needs a redeploy with this app's registry entry. |
Questions
Email sent.tip.web.app@gmail.com — a human reads it.