A sales platform for the digital world.
SaaS subscriptions, booking, CMS, software stores, an internal token economy, a first-class plugin system across three runtimes, and 20+ payment methods — one self-hosted backend, two Vue front-ends, infinite extensions.
VBWD is the missing layer between "I have a product" and "I'm taking real money". Subscriptions, accounts, invoices, taxes, payments, CMS pages, and a token economy — installed once, extended forever via plugins.
Tiered plans, add-ons, prorated upgrades, dunning, cancellation flows. Not a single payment provider — a marketplace of them.
Drop-in Python plugin SDK, typed Vue plugin SDK, event bus, DI container. Extend without forking the core.
Multi-tenant routing, brand-able admin, CMS pages, white-label payment selectors. One stack, many clients.
Built-in token bundles, usage metering, LLM billing. Sell AI features without writing the meter.
Every corner of VBWD is its own runtime with the same plugin contract. A new feature lights up by shipping a coordinated trio: a backend plugin that adds the API + data model, an fe-admin plugin that adds the configuration UI, and an fe-user plugin that adds the customer surface. Or any subset — they're independent.
/api/v1/*, SQLAlchemy 2.0, dependency-injector, event bus,
Alembic migrations. Plugins register Flask blueprints, models, event handlers,
line-item handlers, shipping providers, and admin permission scopes.
addRoute,
createStore, addComponent, addTranslations.
Topological dependency resolution; circular dependencies caught at install time.
${VAR_DIR}/plugins/ — backend writes, both frontends mount it read-only.
No localStorage drift, no per-browser inconsistency.
A single plugin entry can register code into all three runtimes at once. Each runtime exposes a typed surface so plugins can extend it without forks, monkey-patching, or "please rebuild the core" tickets.
/api/v1/<plugin>/*, mounted automatically when the plugin enables.subscription.created, payment.captured, …) on a typed bus.sdk.addRoute().sdk.createStore().DISCOVERED → REGISTERED → INITIALIZED → ENABLED ↔ DISABLED
(with an ERROR state for safe failure). Persistent across restarts via the
plugin_config table; the backend is the only writer.
get_blueprint() + get_url_prefix() auto-mount under /api/v1/<plugin>/* on enable, unmount on disable.
SQLAlchemy 2.0 entities tied to the plugin. Migrations applied on enable, optionally rolled back on uninstall.
register_event_handlers(bus) — listen to subscription, payment, checkout, security events. No polling.
Emit plugin events that other plugins consume. Cross-plugin coordination without direct imports.
Plug into checkout totals: discounts, taxes, shipping, token deductions. Each handler is a pure function over the cart.
Register concrete shipping cost calculators (flat-rate, weight-based, region-based) consumed by the order pipeline.
Contribute product / content categories with their own URL prefixes — picked up by routing rules at the edge.
Declare admin_permissions / user_permissions. Surfaces in the admin RBAC matrix; gates fe-* routes.
on_enable() — runs migrations, seeds data, registers handlers.on_disable() — unhooks handlers, halts background tasks.plugin_config; auto-rehydrated on app boot.get_config(key) / set_config(key, val) — namespaced KV store per plugin.PluginMetadata.Admin plugins are loaded by the host shell at boot. The shell keeps the chrome — login, layout, top-bar, theme — and yields every interior surface to plugins. A plugin can ship a single dashboard widget or a whole subsystem; the contract is the same.
Sidebar entries with icon, label, route, permission scope, and badge. Order is computed from priority + plugin install order.
Full-page Vue components mounted into the admin router. CRUD scaffolds + table / form / detail patterns provided by fe-core.
Drop-in cards on the home dashboard — KPIs, charts, recent activity. Self-fetching, plugin-namespaced data sources.
Plugin config screen auto-bound to get_config / set_config on the backend. JSON-schema-driven form generation.
Declarative v-permission on routes, menu, action buttons. Drives both UI hiding and server-side enforcement.
Locale dictionaries merged into the host i18n. New languages light up across every plugin's UI without per-plugin work.
${VAR_DIR}/plugins/fe-admin-plugins.json at boot. Toggling a plugin
on the backend immediately changes what the next admin login sees — no rebuild, no redeploy.
Active sessions, MRR, churn, top plans, recent activity. Widgets contributed by every enabled plugin.
List, search, edit, impersonate. RBAC matrix per role. Token-balance and invoice-history tabs in user detail.
Tiered plans with categories, pricing, trial, billing-period rules. Add-ons attach to plans or stand alone.
List, filter by state, manual upgrade / downgrade / cancel. Dunning view for past-due accounts.
List + detail, payment status, capture / refund actions, downloadable PDFs.
Per-provider configuration screens — keys, webhooks, test toggles, country availability.
Bundle catalogue, pricing, currency. Used by every metered plugin (LLM-Chat, Taro, …).
Outbound webhook subscriptions — pick events, set endpoint, view delivery log + retry queue.
Routing rules per domain / subdomain / path prefix — drives multi-tenant front-end config.
Tax rules per jurisdiction, currency selection, country-availability matrix used by checkout.
List backend / fe-admin / fe-user plugins, enable / disable, jump to the plugin's settings panel.
App config, email templates per locale, SMTP credentials, dunning schedules.
The user app is a single Vue 3 build that serves both the customer dashboard (account, plans, invoices, tokens) and any public surface a plugin contributes (CMS pages, shop catalogue, public chat, booking pages). Routing rules at the edge decide which audience hits which mount point.
IPlatformSDK exposes
addRoute · createStore · addComponent · addTranslations. The
PluginRegistry resolves dependencies topologically and refuses
to install on a missing peer or cycle.
Every SaaS needs landing pages, docs, FAQs, blog posts, and feature tours. Most teams glue WordPress next to their app and pay the integration tax forever. VBWD's CMS plugin is a first-class citizen of the same Vue runtime, the same auth, the same plugin bus, the same i18n.
Slug-routed pages with rich-text body, metadata, SEO fields, locale variants. Versioned with draft / publish workflow.
Layouts compose pages from reusable widgets — hero, pricing table, FAQ, testimonials, plugin-contributed components.
Multi-level menus, category taxonomies, internal-link guarantees. Menu changes are a CMS edit, not a frontend deploy.
Upload, transform, attach. Stored under ${VAR_DIR}/cms/; served via the same edge cache as the app.
Locale per page. Falls back to default language if a translation is missing — the language switcher never breaks.
Inline admin overlay on rendered pages — click an element, edit it, save. Skips the round-trip to the back-office UI.
Block-based editor — hero, copy, image, columns, embed, plugin-contributed components. JSON-stored, render-time-composed.
Draft + publish + scheduled publish. Diff between versions; revert in one click. Full audit log of who changed what.
Per-page, per-block translations. Bulk translation export / import. The language switcher uses the page locale, not URL hacks.
Title, description, OG image, canonical, robots. Sitemap auto-generated; redirects table for retired pages.
On-the-fly resize / format conversion (WebP, AVIF). Width hints in the editor; srcset emitted to the browser.
Form widget — captures leads, posts to an event on the bus. Other plugins (email, mailchimp, ghrm) listen and act.
Multi-level navigation editor. Permission-aware: a CMS-page-only audience never sees admin links.
Subdomain / path-prefix / locale routing — same engine that powers multi-tenant. CMS pages bind to specific tenants.
cms_page · slug, locale, layout_id, status, seo, bodycms_layout · named layout, ordered widget slotscms_widget · type, props (JSON), order, layout_idcms_menu · tree of menu nodes, page or external linkcms_category · taxonomy for pages + productscms_image · upload + transform metadata9 providers · 20+ payment methods · one checkout flow.
Every payment provider in VBWD is a backend plugin implementing the same
PaymentProviderPlugin interface — create_payment_intent,
capture_payment, refund_payment, and a webhook handler.
fe-user contributes the matching checkout component. Adding a tenth provider is
one plugin, not a core change.
Cards, SCA / 3DS2, subscriptions, ACH, SEPA. Webhooks reconciled against the provider as source of truth.
Smart Buttons + redirect, Vault, Pay Later / BNPL, Apple Pay through PayPal, disputes flow.
Russia / CIS — cards, SberPay, Yandex.Kassa, e-wallets, bank transfers.
LatAm / Brazil — cards, boleto, account transfer, regional installments.
Mexico / LatAm — cards, OXXO cash voucher, SPEI bank transfer, monthly installments.
Korea — cards, virtual accounts, mobile-carrier billing, KRW-native flows.
Thailand — TrueMoney e-wallet integration, in-app QR confirmations.
Thailand — QR-code bank-transfer payments, real-time confirmations.
Google Pay tokens via the C2P2 plugin. Mobile-first checkout with one-tap completion.
Apple Pay tokens via the C2P2 plugin. Domain-association handled by the plugin.
Sister plugin — shipping cost calculator that plugs into the same line-item pipeline as payments.
Implement PaymentProviderPlugin, ship a fe-user checkout component. Two files; live in one enable.
Each one a complete feature; each one optional; each one composable.
Mainchat is the public-facing conversational surface — pre-sales questions, support intake, lead capture. It does not bill tokens; it is free for the visitor. Conversations land in the same admin inbox as authenticated chats, so support never has two queues.
lead.captured on the bus — email plugin, Mailchimp plugin, GHRM listen and act.Inside any thread, a user can send tokens to another user with one
tap — gift, tip, refund, peer-to-peer transfer. Same wallet primitive
(UserTokenBalance) the rest of the platform uses; the
chat surface is the UX.
Mainchat events drive token flows: lead.captured ⇒ auto-credit
the referrer · "priority response" purchase ⇒ token deduction ·
support tip ⇒ transfer to the operator's account. Events on the
same bus the platform already uses.
Every in-chat transfer creates two ledger entries (sender / recipient)
and emits tokens.transferred. Admin can reverse from the
same inbox where the conversation lives. Daily caps + velocity rules
apply.
The booking plugin turns any account into a bookable resource — consultations, classes, equipment rental, room reservations, telemedicine slots. It composes with subscriptions (a plan can include N bookings / month), payments (charge per slot), and the token economy (book by spending tokens).
Resources expose availability windows; slots are the bookable unit. Buffer time, lead time, capacity per slot, recurring patterns.
Beyond time slots — physical inventory (rooms, equipment) with stock counts, holds during checkout, automatic release on timeout.
Customer-side flow with policy enforcement (free up to N hours before, partial refund window, no-show fee).
Emits booking.created · confirmed · cancelled · noshow. Email plugin sends confirmations; calendar plugin syncs to Google / Outlook.
Plan defines monthly booking allowance; quota enforcement runs at booking time. Overflow can charge tokens or block.
Resource calendar, booking list, no-show register. Bulk reschedule when a resource goes offline.
The shop plugin gives VBWD a product catalogue alongside the subscription model. One-time purchases, downloadable products, license keys, physical goods. The checkout, the payment providers, the tax engine, the discount codes — all shared with subscriptions. Two billing models, one storefront.
Products with variants (size, license tier, region). SKU-level inventory, per-variant pricing, category taxonomy from the CMS.
Multi-item, multi-currency, per-region tax preview. Shared session with the rest of the user app — never "where did my cart go".
Order list with state machine (pending → paid → fulfilled → shipped → delivered). Refund and partial-refund flows on every state.
RMA flow — customer-initiated, admin-approved, refund auto-issued through the original payment provider.
For software products — generate, deliver, revoke. Customer can view their keys in the dashboard, regenerate on lost-key request.
Time-limited signed URLs for digital products. Per-customer download caps. Watermarking hook for plugin extension.
Composes with shipping provider plugins (flat-rate ships out of the box; weight-based or carrier-API plugins drop in).
order.created · paid · fulfilled · shipped · refunded · returned — fan out to fulfillment, accounting, CRM.
LLM-Chat is the metered AI surface. Every message round-trip costs tokens drawn from the user's balance — sourced either from a subscription's monthly grant or from a token bundle they bought outright. The plugin only knows the LLM provider and the messages; the meter, the balance, the bundles, the receipts come from VBWD.
Taro is an AI tarot-reading plugin: pick a question, draw cards, get an interpretation written by an LLM. It exists as the canonical demo of how a metered AI experience plugs into VBWD: subscribe to a plan, get N readings included, buy more when you run out. Every piece runs on platform primitives — there is no bespoke billing inside Taro.
Multiple spreads (single card, three-card, Celtic cross). Draw is server-side; the deck state is auditable in the admin panel.
Prompt template per spread, configurable from the admin. Output streamed to the user; full transcript saved to history.
The customer revisits past readings. Admin sees the same data for support and quality review.
Models · events · services · DI · SOLID · security.
Every domain in VBWD has a small, named set of SQLAlchemy 2.0 entities. New plugins add their own; the core never grows by accretion. The list below is what the platform ships with on day one — what every plugin can rely on existing.
User, UserDetails, UserAccessLevel, RoleUserTokenBalance — the walletPasswordResetTokenFeatureUsage — quota trackingTarifPlan, TarifPlanCategorySubscription — state machine, renewal, dunningAddOn, AddOnSubscriptionTokenBundle, TokenBundlePurchaseInvoice, InvoiceLineItemPaymentMethod — provider + customer-instrumentTax, Country, Currencyplugin_config — enable / disable + per-plugin KVWebhook subscriptions + delivery logThe event bus is the platform's spinal cord. Every meaningful state change emits a typed domain event; plugins subscribe to what they care about. Email confirmations, analytics, Mailchimp sync, dunning, GHRM access grants — none of them are wired into the services that triggered them.
subscription.created · activated · cancelled · expired · dunningpayment.authorized · captured · failed · refunded · refund.reversedcheckout.initiated · completedsecurity.password_reset.request · execute · login.failedplugin.registered · initialized · enabled · disabledchat.tokens.consumed, booking.created, order.fulfilled, lead.captured
The core uses dependency-injector to wire repositories, services,
and infrastructure (database session, Redis client, event bus, secrets provider).
Every consumer asks for what it needs; nothing reaches for it through a global.
The container is configured once at app start and overrideable in tests.
One Container per app, declared as a class with typed providers — singletons, factories, configurations, resources.
Routes, services, plugins receive collaborators via constructor injection. @inject at the edges; pure constructors elsewhere.
In tests, providers are swapped: in-memory repositories, fake event bus, deterministic clock. No service knows it's been mocked.
AuthService, UserService, SubscriptionServiceInvoiceService, RefundService, TokenServicePluginService · enable / disable / configWebhookService, EmailServiceEventDispatcherUserRepository, SubscriptionRepository, InvoiceRepository, …Routes validate. Services orchestrate. Repositories persist. Models describe shape. Event handlers react. When a class wears two hats, the test suite gets harder to read — and that's the smell that triggers a split.
Every extension point is a contract: BasePlugin, PaymentProviderPlugin, line-item handler, shipping provider, event subscriber. New behaviour ships as a new class implementing one of these — never as an if <tenant>: in the core.
Stripe, PayPal, Conekta — same interface, same return shapes, same exception surface. The checkout service does not branch by provider. If a provider can't honour the contract (e.g. no partial refund), it fails the same way every other provider would.
The plugin SDK is split: get_blueprint, register_event_handlers, register_line_item_handlers, register_shipping_providers. A plugin that only emits events doesn't need to know any of the others exist.
Services receive repository interfaces. The container injects the SQLAlchemy implementation in production, an in-memory one in tests. Plugins consume the event bus interface, not its in-process implementation — so the upgrade to a durable queue is a wiring change, not a rewrite.
Bearer tokens with short TTL + refresh. Signed with a per-deploy secret; rotated without invalidating live sessions.
Roles + access levels. Plugins declare their own permission scopes; the matrix is editable from the admin UI.
Public endpoints rate-limited per IP and per user. Login + password-reset flows have stricter caps + lockouts.
Time-limited single-use tokens. Same response shape on success and on unknown email — no enumeration leak.
Outbound webhooks signed with HMAC; inbound (from payment providers) verified before any state change.
Order creation, payment capture, refund — all idempotent against an idempotency-key column. Retries are safe.
Every privileged action recorded — who, when, what, from where. Plugins extend the schema with their own audit entries.
Provider keys via env vars or vault references — never in code, never in plugin_config. Fail-closed on default secrets.
login.failed events feed velocity-based blocks.47 public repos under VBWD-platform. BSL 1.1 — self-host for free, license needed only at production scale.
Everything VBWD ships lives in one GitHub organisation. The architecture is in the open, the licensing is honest, and the plugin model means you can ship a feature without ever touching core. Three pillars — that's the whole pitch.
github.com/VBWD-platform hosts the full SDK plus every plugin as its own repo. Each plugin can ship at its own cadence; the umbrella SDK pins the versions that compose into a release.
Source-available under the Business Source License 1.1. Self-host for development, evaluation, and personal use without a commercial licence. Production use at scale → talk to us. Nothing hidden, nothing rugged.
A backend plugin and its fe-user / fe-admin counterparts live in three independent repos. Build, test, release them separately. The SDK glues them together via standard Python and Vue plugin contracts — no fork.
The runtime that boots before any feature loads — auth, sessions, plans,
invoices, events, the plugin loader. Read the code, run the test suite, file
an issue. Everything below is one git clone away.
Recipes, dev-install scripts, integration test harness. Start here to spin up the whole stack on a laptop in under five minutes.
The API — auth, billing, CMS, plugin host, event bus, DI container. Postgres + Redis. Drop-in plugins via standard Python imports.
The user-facing SPA — dashboard, checkout, plan picker, invoices, language switcher. Plugins inject their own routes + stores at boot.
The back-office SPA — plans, users, invoices, plugin settings, content moderation. Same plugin contract as fe-user; same hot-reload story.
Each plugin trio — backend + fe-admin + fe-user — is a complete feature you can ship as-is or fork. Mix and match: a hotel ships booking + cms; a SaaS ships subscription + meinchat; a creator marketplace ships shop + discount. The core never changes.
Drop-in CMS with theme switcher, page-level access control, and a widget registry that other plugins extend.
Calendars + bookable resources. Doctors, hotels, classrooms — same engine, different config. Includes admin moderation + user self-service.
Storefront catalogue + warehouse inventory + checkout flow. Pairs with discount for coupons and shipping_flat_rate for fulfilment.
Nicknames, address book, image attachments, peer-to-peer token transfer. Admin moderation: ban, audit, inspect any conversation.
Tiered plans, add-ons, prorated upgrades, dunning, cancellation. The billing backbone every paying instance depends on.
Token-billed AI conversation, tarot reading skin. Reference for how to ship an LLM feature with billing already wired.
vbwd-plugin-<name>,
vbwd-fe-user-plugin-<name>,
vbwd-fe-admin-plugin-<name> — three repos per feature, each
with its own tests and CI.
Every payment provider is a plugin — drop in the rails your market uses, ignore the rest. Card-first markets get Stripe / PayPal. Local-rail markets get Pix, OXXO, KakaoPay, PromptPay, TrueMoney. One checkout flow, many settlement paths.
The conversion lift on the checkout page that every market still expects.
Cards, SBP, MIR, Yandex Pay. SBP QR is the standout.
2C2P v4: cards + PromptPay + PayNow + GCash + MoMo through one gateway.
7 countries: Pix, Boleto, OXXO, SPEI, PSE, Webpay, cards.
Widget checkout, KakaoPay, Naver Pay, cash receipts (현금영수증).
Direct QR + deep-link. The wallet most Thai customers already have.
Direct QR + bank-webhook reconciliation. No aggregator markup.
Talk to us. Buy a license. Build a business on VBWD.
We're a small team. The fastest path from "interesting" to "we can do this" is a single call — your stack, your billing problem, our take, your decision. No sales engineering, no deck-driven demo. Bring your hardest question.
hello@vbwd.cc — start with three lines: your stack, your billing question, your timeline.
Open an issue in the public repo with your question. Other readers benefit; you get a public, citeable answer.
The license is annual and the price is a single number — no per-seat, no per-transaction, no API call counters. You self-host on your infrastructure (or ours, see managed hosting). Updates included for the year.
If you run a digital agency, a dev shop, or you consult on billing and identity infrastructure, VBWD is a product you can resell. You sell the license + the implementation; we provide the platform, the updates, and tier-3 support. Your client's logo on the dashboard, your name on the contract.
A sales platform for the digital world. One self-hosted backend, two Vue front-ends, one plugin contract, twenty-plus payment methods, an internal token economy, a CMS, a shop, a booking engine, and an extensible AI surface — installed once, extended forever.
./recipes/dev-install-ce.sh