VBWD for Android

⚡ VBWD

A sales platform for the digital world — SaaS subscriptions, CMS, shop, booking and a token economy on one self-hosted backend, two Vue front-ends and one plugin contract.

landing1cmsmainchatchattheme-switcheranalytics
VBWD for Android

A Kotlin + Jetpack Compose port of the iOS app

Android is a faithful iOS port that preserves the exact public contracts — the Plugin interface, the PlatformSdk facade, event names, manifest shape and route/permission semantics — so an iOS or web plugin author maps across 1:1. Built with Kotlin, Jetpack Compose and Hilt; compileSdk 36, minSdk 26, JDK 17.

:app — host

Single-activity @HiltAndroidApp; MainActivity → AppRoot, the composition root (di/CoreModule.kt), and the plugins.json + vbwd_config.json assets.

:core — the SDK

Networking (OkHttp + kotlinx.serialization), domain + session, the plugin system, and the shared Compose screens. Published as com.vbwd:vbwd-android-core.

:plugins:* — features

Depend on :core only — a CI-enforced dependencyBoundaryCheck fails the build on any undeclared edge (the core-agnosticism rule).

The plugin contract

The same seams, in Kotlin

A plugin implements the Plugin interface; all hooks are suspend and all but install default to no-ops. The host loads the manifest, registers the compiled-in plugins, installs the enabled ones in topological dependency order and activates them — every failure isolated to its plugin:

interface Plugin {
    val metadata: PluginMetadata          // name, SemanticVersion, dependencies
    suspend fun install(sdk: PlatformSdk) // register into the app
    suspend fun activate() {}
    suspend fun deactivate() {}
    suspend fun uninstall() {}
}

install receives the PlatformSdk facade — and nothing else — exposing addRoute, addMenuItem, addComponent (Dashboard* / Profile* by prefix), createStore, addTranslations, addPaymentAction, addCheckoutSource, plus the injected api, events and cart. Adding a plugin = a new :plugins:<name> module + an entry in provideAvailablePlugins and plugins.json.

Backend & auth

Config asset, encrypted token store

Configuration lives in app/src/main/assets/vbwd_config.json. Set api_base_url to your instance — use http://10.0.2.2:5000/api/v1 to reach the host's localhost from the emulator, or https://vbwd.cc/api/v1 for the live demo. Login POST /auth/login yields a bearer token persisted with EncryptedSharedPreferences (the Keychain analogue); requests go through a single ApiClient (OkHttp) port that injects the token and maps a 401 to a sign-out event.

The app, screen by screen

Login to LLM bot, all in Compose

Once authenticated, AppShellView renders a top bar, a navigation drawer (Dashboard, Profile, Settings + every plugin's menu items) and the routed content. Material 3 theming flows from a ThemeManager; plugins register their own AppThemes.

Sign in
Sign in
Dashboard — tokens, invoices & plugin widgets
Dashboard — tokens, invoices & plugin widgets
Posts — the CMS, rendered in-app
Posts — the CMS, rendered in-app
Chat — rooms & inbox
Chat — rooms & inbox
A conversation
A conversation
Send tokens to another user
Send tokens to another user
Token-transfer receipt in the thread
Token-transfer receipt in the thread
LLM bot — choice cards & cart
LLM bot — choice cards & cart
Profile
Profile
The plugin-driven navigation drawer
The plugin-driven navigation drawer

Captured from the live Android build talking to vbwd.cc. The iOS app renders the same screens.

Plugin modules

What's in the build

meinchat

Multi-room chat: SSE message streaming, image attachments, peer-to-peer token transfers, bot meta-content (choices/menu/cart cards).

meinchat-plus

Secure-messaging extension (crypto protocol); declares a dependency on meinchat.

cms

Config-driven “Posts” browser over the host CMS embed — page/post/video/PDF through one WebView.

subscription

Tarif-plan + add-on browser, subscription overview, dashboard widget, a subscription checkout source.

token-payment

Token-balance payment method — quote + charge, registers the “token” payment action.

stripe

Stripe checkout-session payment method with a WebView redirect section.

invoice

Invoice-info payment method — registers the “invoice” action + info section.

tarot

Tarot reading feature; draw/reading routes, independent of commerce.

example

Reference plugin exercising every PlatformSdk seam — the canonical new-plugin template.

Build & run

One Gradle task

  • Point api_base_url in app/src/main/assets/vbwd_config.json at your backend.
  • Build & install to a device/emulator: ./gradlew :app:installDebug (app id com.vbwd.app).
  • The quality gate — ./gradlew check dependencyBoundaryCheck — is what CI runs (ktlint + detekt + unit + boundary).

Same contract, different runtime: see the iOS guide for the SwiftUI original, or the plugin system for how a feature lights up across web, iOS and Android at once.