@moneybar.online/moneybar
v12.1.3
Published
The navbar of monetization. Fix the 3 money-blocking stages: forced sign-ins, silent drop-offs, and broken payment flows. Turn browsers into buyers.
Maintainers
Readme
MoneyBar
The navbar that turns free users into paying customers. Authentication, usage limits, payment checkout, and subscription management — all in one component. No backend required.
Quick Start
Step 1: Create your config file
Create moneybar-config.js in your project:
import { MoneyBar } from 'https://cdn.jsdelivr.net/npm/@moneybar.online/[email protected]/dist/index.bundle.js';
const moneyBar = new MoneyBar({
// ── Required ────────────────────────────────────────────────
security_key: 'sk_...', // Get from MoneyBar dashboard
actionLabel: 'PDF Exports', // Shown in navbar: "PDF Exports: 2/3"
freeAttemptLimit: 3, // Free attempts before paywall
// ── Payment (required for paid plans) ───────────────────────
payment: [{
provider: 'dodo',
productId: 'pdt_xxx', // From Dodo Payments dashboard
mode: 'live', // 'test' or 'live'
name: 'Pro', // Badge label shown in navbar
description: 'Unlimited exports, no watermarks' // Shown in paywall modal (optional)
}],
// ── Feedback form (optional) ─────────────────────────────────
feedback: {
form: {
title: 'Quick Feedback',
description: 'What stopped you from upgrading?',
option1: 'Too expensive',
option2: 'Not enough features',
option3: 'Need more time to evaluate'
},
email: [{
provider: 'resend',
apiKey: 'your-resend-api-key',
fromEmail: '[email protected]'
}]
},
// ── Theme (optional) ─────────────────────────────────────────
theme: {
name: 'emerald', // DaisyUI theme name
primaryColor: '#059669' // Hex color for buttons and accents
},
// ── Navbar title & links (optional) ──────────────────────────
titleBar: {
title: 'My App',
links: [
{ text: 'Features', url: '#features', target: '_self' },
{ text: 'Pricing', url: '#pricing', target: '_self' }
]
},
// ── ⚠️ DO NOT MODIFY ─────────────────────────────────────────
// MoneyBar's backend — handles auth, payments, and usage tracking.
// This is pre-configured. Changing these values will break MoneyBar.
supabase: {
url: 'https://qhlzdkwcrrjjcqvupyaa.supabase.co',
anonKey: 'eyJhbGci...'
}
});
// Make it accessible from your other scripts
window.moneyBar = moneyBar;Step 2: Add to your HTML
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<button id="export-btn">Export PDF</button>
<!-- Load your MoneyBar config -->
<script type="module" src="moneybar-config.js"></script>
<!-- Attach MoneyBar to your action buttons -->
<script type="module">
// Wait for MoneyBar to initialize
window.addEventListener('moneybar:ready', () => {
window.moneyBar.attachToButton('#export-btn', async (userContext) => {
if (userContext.isPremium) {
await exportPDF(); // unlimited
} else if (userContext.remaining > 0) {
await exportPDF(); // uses 1 free attempt
}
// If remaining === 0, MoneyBar shows the paywall automatically
});
});
</script>
</body>
</html>Step 3: Configure Dodo webhooks
MoneyBar needs Dodo to notify it when payments complete. In your Dodo dashboard:
- Webhooks → Add endpoint
- URL:
https://qhlzdkwcrrjjcqvupyaa.supabase.co/functions/v1/verify-payment - Signing secret: provided to you with your security key — paste it as the webhook signing secret in Dodo
- Subscribe to:
payment.succeeded,subscription.active,subscription.renewed,subscription.updated,subscription.cancelled
Without this step, users who complete checkout will not get premium access. The signing secret is used to verify that webhook calls genuinely come from Dodo. Do not share it publicly.
NPM / Build Tool Projects
npm install @moneybar.online/moneybarimport { MoneyBar } from '@moneybar.online/moneybar';
const moneyBar = new MoneyBar({ ...config });UserContext Reference
Every attachToButton callback receives a userContext object:
window.moneyBar.attachToButton('#btn', (userContext) => {
// ── Access ───────────────────────────────────────────────────
userContext.isPremium // boolean — has active paid access
userContext.isAuthenticated // boolean — is signed in
userContext.isLapsed // boolean — was premium, subscription ended
// ── Usage limits ─────────────────────────────────────────────
userContext.currentCount // number — times used so far
userContext.remaining // number — free attempts left
userContext.limit // number — total free limit
// ── User info ─────────────────────────────────────────────────
userContext.email // string — user's email (if signed in)
userContext.name // string — user's name (if available)
// ── Subscription (only when isPremium: true) ──────────────────
userContext.subscriptionType // 'day' | 'month' | 'year' | 'one-time'
userContext.subscriptionId // string — Dodo subscription ID
userContext.subscriptionExpiresAt // ISO string — access expires at
userContext.subscriptionDaysRemaining // number — days until expiry
userContext.isSubscriptionActive // boolean — false if cancel is scheduled
userContext.cancelAtNextBillingDate // boolean — cancellation scheduled
userContext.nextBillingDate // ISO string — next renewal date
userContext.customerId // string — Dodo customer ID
});State examples
Free user (not signed in):
{ isPremium: false, isAuthenticated: false, isLapsed: false, remaining: 3, limit: 3 }Free user (signed in, hasn't paid):
{ isPremium: false, isAuthenticated: true, isLapsed: false, email: '[email protected]', remaining: 1, limit: 3 }Active subscriber:
{
isPremium: true,
subscriptionType: 'month',
subscriptionId: 'sub_xxx',
subscriptionExpiresAt: '2026-07-10T07:29:45Z',
subscriptionDaysRemaining: 30,
isSubscriptionActive: true,
cancelAtNextBillingDate: false,
nextBillingDate: '2026-07-10T07:29:45Z',
customerId: 'cus_xxx'
}Subscriber who scheduled a cancellation:
{
isPremium: true, // still has access until billing date
isSubscriptionActive: false,
cancelAtNextBillingDate: true,
subscriptionExpiresAt: '2026-07-10T07:29:45Z'
}Lapsed subscriber (subscription ended):
{ isPremium: false, isLapsed: true, email: '[email protected]', remaining: 0 }Common Patterns
Premium vs free quality
window.moneyBar.attachToButton('#export-btn', async (userContext) => {
if (userContext.isPremium) {
await exportHighQuality();
} else if (userContext.remaining > 0) {
await exportStandard();
}
// paywall shown automatically when remaining === 0
});Prevent count increment on error
window.moneyBar.attachToButton('#convert-btn', async (userContext) => {
try {
await convertImage();
// count increments only on success
} catch (err) {
showError(err.message);
throw err; // re-throw → count does NOT increment
}
});Multiple buttons, same logic
function handleExport(userContext) {
if (userContext.isPremium) runExport();
}
window.moneyBar.attachToButton('#btn-png', handleExport);
window.moneyBar.attachToButton('#btn-pdf', handleExport);
window.moneyBar.attachToButton('#btn-csv', handleExport);Different buttons, different actions
window.moneyBar.attachToButton('#export-btn', ctx => { if (ctx.isPremium) exportPDF(); });
window.moneyBar.attachToButton('#convert-btn', ctx => { if (ctx.isPremium) convert(); });attachToButtons — bulk attach with selector map
window.moneyBar.attachToButtons({
'#export-btn': (ctx) => { if (ctx.isPremium) exportPDF(); },
'#convert-btn': (ctx) => { if (ctx.isPremium) convert(); }
});What MoneyBar Handles Automatically
| Feature | Detail |
|---|---|
| Authentication | Google sign-in (more providers coming) |
| Usage tracking | Counts per user per app, resets per plan |
| Payment checkout | Dodo Payments checkout flow |
| Subscription management | Renewal, cancellation, resubscription |
| Customer portal | Self-service subscription management via "Manage Payments" |
| Help & support | Built-in ? icon → contextual help modal + support email form |
| Caching | Premium status cached 24h; usage count cached 60s |
| Multi-app | Same user across multiple apps, separate limits per app |
Configuration Reference
| Key | Required | Description |
|---|---|---|
| security_key | Yes | App identifier — get from MoneyBar dashboard |
| actionLabel | Yes | What users are doing, shown in navbar |
| freeAttemptLimit | Yes | Free attempts before paywall (0 = always paywalled) |
| payment | For paid plans | Dodo product config (provider, productId, mode, name, description) |
| feedback.form | No | Quick Feedback modal options |
| feedback.email | No | Resend config for feedback + support emails |
| theme | No | DaisyUI theme name + primary hex color |
| titleBar | No | Navbar title and nav links |
| supabase | Yes | Pre-configured — do not modify |
Getting a Security Key
MoneyBar is currently in private beta.
- Email: [email protected]
- GitHub: Open an issue
Support
- Issues: GitHub Issues
- Docs: moneybar.online
License
MIT
