monigo.co/portal/<token>.
All four deliver the same building blocks (invoice list, wallet card, subscription card, etc.) and the same opinionated composed portal (
<MonigoPortal />). They share a common core: @monigo/portal-core (typed API client + state machines) and @monigo/tokens (CSS variables and theming helpers).
How it fits together
Your backend generates a portal token (see Customer Portal). Your frontend drops in<MonigoPortal /> with that token. Done.
Install
Quick start (the 5-minute integration)
The flow is always the same:- Your backend mints a portal token and hands it to your frontend.
- Your frontend renders
<MonigoProvider>with the token and drops in<MonigoPortal />.
1. Mint the token on your server
Node.js / Server
2. Render the portal on the client
<MonigoPortal /> renders its own navigation, routing, and all feature pages — dashboard, invoices, bills, subscriptions, wallets, payment methods, payout accounts.
Building-block composition
If you want the data and behaviour but not the opinionated layout, use the building-block components directly. They share the same<MonigoProvider> context and run independently.
Exported building blocks
The same component names exist across React, Vue, and Svelte. Flutter widgets follow Dart’ssnake_case → Pascal convention (InvoiceList, invoice_list.dart).
Theming
Monigo’s components render against a set of CSS custom properties. The defaults are sensible; the ones you usually want to change areprimary, accent, and mode.
Quick theming via props
mode accepts 'light', 'dark', or 'auto'. With auto, the portal follows the user’s system preference via prefers-color-scheme.
Full theme API (web packages)
Theming via CSS (any host app)
Every token is a plain CSS variable. Override any of them on any ancestor element:@monigo/tokens/monigo.css — or use the typed TOKEN_NAMES array:
Runtime theme generation (per-tenant)
If you render the portal for multiple tenants with different brand colors, inject a scoped theme at runtime:Using your own router
The<MonigoPortal /> component bundles a lightweight internal router so the 5-minute demo stays a one-liner. For production apps that already have a router (Next.js App Router, Nuxt, SvelteKit, Remix, TanStack Router), import the page components and wire them into your own routes.
Exported page components
Customer actions
Every action component fires an optionalonError callback for telemetry and emits a success callback you can use to refresh state or navigate.
Pay an invoice
React
PayInvoiceButton calls POST /portal/invoices/:id/pay, which returns a gateway authorization_url. The component redirects the browser to that URL automatically.
Cancel a subscription
Svelte
window.confirm. The backend call happens only after confirmation.
Add a payment method
Vue
unsupported and shows a localized message.
Wallet top-ups
Flutter
POST /portal/wallets/:id/fund, and redirects to the gateway.
Error handling
Every component renders three states out of the box: loading (skeleton), empty (“you have no invoices yet”), and error (with a Try again button). You can override any of them.SSR & server components
All web packages are SSR-safe. The components don’t touchwindow, document, or localStorage at module scope — only inside framework lifecycle hooks.
The portal fetches data on the client regardless — portal tokens are customer-scoped and we don’t want them pre-fetched on a shared cache. The initial HTML shows skeletons; the data streams in after hydration.
i18n
v1 ships English. All user-visible strings live in a typed catalog you can override:React
MessageKey union from @monigo/portal-core.
Proxying the API (advanced)
By default, every component callshttps://api.monigo.co/api/v1/portal/* directly from the browser with the X-Portal-Token header. If your security policy requires all traffic to flow through your own backend, pass a custom baseUrl and fetch:
/api/monigo/* to https://api.monigo.co/api/v1/* and injects the X-Portal-Token header (or validates one from a cookie you control).
Bundle size
Tree-shaking works end-to-end. A minimal integration (provider +InvoiceList only) ships well under 20 kB min+gzip in React, Vue, and Svelte. The full <MonigoPortal /> is under 60 kB min+gzip per framework.
Flutter’s monigo_portal adds roughly 450 kB to release APKs (mostly from generated models). It uses dart:http — no extra native plugins — so it compiles unchanged for iOS, Android, web, macOS, Linux, and Windows.
Publishing targets
The web packages use synchronised versioning — they bump together via Changesets. Flutter ships its own cadence.
Related
- Customer Portal — how portal tokens work and the hosted portal at
monigo.co/portal/<token> - Authentication — where portal tokens fit in the auth model
- Invoice Lifecycle — the state machine behind
InvoiceStatusBadge - Subscription Lifecycle — what
CancelSubscriptionButtontriggers

