quietjar
For developers

A support button for your docs site.

One script tag. No layout shift. Give it a goal and it hides once the goal is met. Fully configurable.

Install

<script>
  window.QuietJar = {
    "site": "qj_your_site_id",
    "currency": "eur",
    "amounts": [3, 5, 10],
    "labels": {
      "headline": "Support this site",
      "body": "Enjoying the docs? Buy us a coffee.",
      "action": "Tip"
    },
    "style": { "color": "#0369a1", "font": "rounded" },
    "close": { "enabled": true, "after": "session" },
    "position": { "corner": "bottom-right" }
  };
</script>
<script src="https://quietjar.com/js/latest/quietjar.js" async></script>
  1. 01Copy the snippet and paste it into your page's HTML.
  2. 02Fill in your site id from the dashboard. If you are logged in on this site, it is already filled in.
  3. 03Adjust the settings below. Every one of them has a default, so the snippet works as pasted.

Plain HTML shown here. Astro, Hugo, Docusaurus, and VitePress work the same way: the snippet goes in the layout or in the page.

Settings reference

The widget reads its settings from a window.QuietJar object on the page, before the script tag loads. Every setting has a default; site is the only one with a visible consequence when it is missing.

TypeRequiredDefaultWhat it does
sitestringyes—

Your public site key from the dashboard. Without it the widget renders, but the checkout cannot take payments.

currencystringnoeur

ISO 4217 three-letter code, case-insensitive. The bounds and preset amounts follow the currency. An unknown code falls back to eur.

goalstringno—

A goal id from the dashboard. When set, the card renders a progress meter for it.

goalReachedstringnohide

What the widget does once the goal is reached. Ignored without a goal. Anything else falls back to hide.

hide
The widget stops rendering, so the page no longer asks.
show
The widget stays and keeps taking donations, without the bar.
show-with-bar
The widget stays and keeps the filled bar.
amountsnumber[]noper-currency presets

Amounts offered in the checkout, in major units. At most 4 are kept, deduplicated and sorted. Entries that are not finite numbers or sit outside the currency's bounds are dropped; if none survive, the presets are used.

labels.headlinestringno—

The button label. When unset, the widget renders as an icon-only pill whose accessible name falls back to "Support this site".

labels.bodystringno—

The card body. When set, the widget renders as a card with a headline and an action button instead of a pill button.

labels.iconstringnopiggy

The icon on the button: any text glyph, or piggy for the pig mark. An empty string removes the icon. A value longer than 8 characters falls back to the default.

labels.actionstringnoSupport

The card's action button label.

labels.closestringnoDismiss

The accessible name of the close control.

labels.thanksstringnoThank you for your support

Shown in the checkout once a tip succeeds.

labels.otherstringnoOther

The label of the free-entry amount option.

labels.minimizestringnoMinimize

The accessible name of the control that collapses the checkout.

style.colorstringno#0369a1

The accent color as a hex value: #rgb, #rgba, #rrggbb or #rrggbbaa. Anything else falls back to the default.

style.fontstringnorounded

The font stack the widget uses. Anything else falls back to rounded.

system
The platform's own UI font, such as San Francisco or Segoe UI.
serif
A system serif, such as Georgia or Charter.
rounded
A rounded system font, such as SF Pro Rounded. Falls back to the system font where none is installed.
mono
A system monospace font, such as SF Mono or Cascadia Mono.
inherit
The page's own font stack.
style.cssstringno—

Raw CSS appended after the widget's own stylesheet, for overrides the settings above cannot express.

close.enabledbooleannotrue

Whether the close control visitors can use to dismiss the widget is shown.

close.afterstringnosession

What a visitor closing the widget does to its visibility. Anything else falls back to session.

session
Hidden until the next visit.
days
Hidden for close.days.
never
Reappears on the next page load.
forever
Never shown again.
close.daysnumberno7

Days hidden after closing. Only used when close.after is days. A whole number of one or more; anything else falls back to 7.

donation.hideDaysnumberno30

Days hidden after a completed donation, so the widget does not ask again right away. Same whole-number rule as close.days.

position.cornerstringnobottom-right

Where the widget floats. Anything else falls back to bottom-right.

bottom-right
Bottom right corner of the viewport.
bottom-center
Bottom center of the viewport.
bottom-left
Bottom left corner of the viewport.
top-right
Top right corner of the viewport.
top-center
Top center of the viewport.
top-left
Top left corner of the viewport.
mount.targetstring or HTMLElementno—

A CSS selector or element the widget mounts into, inside the page's flow, instead of floating in the fixed corner. Invalid or missing falls back to the corner.

Logged in on this site? Your own site id is filled into the snippet above. Your personalized snippet is also on the widget page in the dashboard.

Examples

amounts
amounts: [3, 5, 10] offers three preset buttons in the checkout, shown in the site's currency.
close.after
close.after: "days" with close.days: 7 hides the widget for a week after a visitor dismisses it.
labels.icon
labels.icon: "☕" puts a coffee cup on the button. labels.icon: "" removes the icon entirely.
position.corner
position.corner: "bottom-center" floats the widget at the bottom center of the viewport.
mount.target
mount.target: "#donate-slot" places the widget inline inside that element instead of the floating corner.

Invalid and missing values

Nothing fails loudly. Every setting falls back to the default listed above when it is missing or invalid, and unusable amounts entries are dropped rather than shown. The only value with visible consequences when missing is site: the widget renders, but the checkout cannot take payments.

Performance

Script size: 38.6 kB (11.7 kB gzipped over the wire). Load time: around 40 ms on a cold cache. The button floats in a fixed corner layer, so it displaces nothing on your page: zero layout shift. Stripe's payment code loads only when someone opens the checkout, not on page load.

How it steps back

After a successful payment, the button enters a quiet state for a while and shows a thank-you instead of asking again. The record lives in the visitor's browser, so nothing is stored on our side and there is no server-side suppression. You pick how long it steps back in the dashboard: 30 days by default. Safari clears browser storage after 7 days without a visit, so a long step-back can end early there. Internally we call it suppression.

Payment methods

Apple Pay
Appears on iPhone, iPad, and Mac. One tap with Face ID.
Google Pay
Appears in Chrome and on Android. One tap, no forms.
Cards
Visa, Mastercard, Amex, Cartes Bancaires. The fallback that always works.
Link
Stripe's own wallet. Returning supporters pay without retyping a card.
iDEAL
For visitors with a Dutch bank. They pay in their own banking app.
Local methods
Bancontact, EPS, Revolut Pay, BLIK, Satispay, Pay by Bank, where available.

Goals

Give the button a public target and a bar that fills toward it: hosting for the year, the next release, a new microphone. Concrete goals lift the amounts people choose. Set one in the dashboard next to the button's style.

Open the panel from your own code

Wire the checkout to your own call to action: the end of an article, a finished download, a tag manager. Call window.QuietJar.open() anywhere on the page and the panel opens right there. It sits next to the widget when that is visible, and centers on the page when it is not. The call always opens, even for visitors the widget stepped back for.