Developers

Coin Moebius

A headless payment router for static sites.

One onSuccess callback. Many gateways. We built Coin Moebius because accepting money on static sites without renting a storefront was harder than it should be. The repo is open source and free for anyone to use.

MIT licensedTypeScriptStatic site friendlyHeadless

Overview

Coin Moebius is a thin browser core plus a verifier core, glued together by provider plug-ins. You bring the buy button. The router takes care of talking to the gateway and turning the gateway’s “they paid” signal into one shared shape your fulfillment code can rely on.

It is built for the JAMstack reality: a static front-end, a handful of serverless functions, and one webhook endpoint that handles every payment method you support. No storefront rental. No vendor lock-in. Add a provider when you need one. Remove it when you don’t.

Tiny core
Install only the providers you need
One callback
onSuccess for every gateway
Strict boundary
Browser core, server verifier — never mixed

Install

Start with the core. The browser core is all you need to build against the API. Add the verifier on the server when you wire up your first webhook. Providers are entirely optional — install them only when you decide how you want to take payment.

1

Install the core

Browser-safe. Zero providers, zero gateway code.

Browsernpm
npm install @aquarian-metals/coin-moebius
2

Add the verifier when you ship a webhook

Server-only. Lives in your serverless function, never in the browser bundle.

Server / serverlessnpm
npm install @aquarian-metals/coin-moebius-server
3

Optional — add a provider

Pick only the gateways you accept. Add more later, remove what you stop using.

Stripe

Card, Apple Pay, Google Pay, hosted Stripe Checkout.

npm install @aquarian-metals/coin-moebius-stripe

Monero / Cryptomus

Privacy-preserving crypto payments via Cryptomus.

npm install @aquarian-metals/coin-moebius-monero-cryptomus

Need something else? Copy packages/providers/template and publish your own under any npm scope.

Pin a real semver range (for example ^0.1.0-beta.1) in your package.json while the line is in beta so installs stay predictable.

Quick start

Two files: a tiny browser bootstrap that wires providers and listens for success, and a single webhook endpoint that verifies any provider you register. The README walks the rest of the surface.

In the browserTypeScript
import { createPaymentManager } from '@aquarian-metals/coin-moebius';
import createStripeProvider from '@aquarian-metals/coin-moebius-stripe';
import createMoneroCryptomusProvider from '@aquarian-metals/coin-moebius-monero-cryptomus';

const payments = createPaymentManager({
  providers: [
    createStripeProvider({ publishableKey: import.meta.env.VITE_STRIPE_KEY }),
    createMoneroCryptomusProvider(),
  ],
});

payments.onSuccess((result) => {
  // Unlock the download. Update your DB. Send the receipt.
  console.log('Paid with', result.provider, result);
});

document.getElementById('buy').onclick = () => {
  payments.initiate({ productId: 'ebook-42', amount: 19.99, currency: 'USD' });
};
On the serverJavaScript
import { registerVerifier, verify } from '@aquarian-metals/coin-moebius-server';
import { createStripeVerifier } from '@aquarian-metals/coin-moebius-stripe/server';
import { createCryptomusVerifier } from '@aquarian-metals/coin-moebius-monero-cryptomus/server';

registerVerifier('stripe', createStripeVerifier({
  endpointSecret: process.env.STRIPE_WEBHOOK_SECRET,
}));

registerVerifier('monero-cryptomus', createCryptomusVerifier({
  merchantUuid: process.env.CRYPTOMUS_MERCHANT_UUID,
  paymentApiKey: process.env.CRYPTOMUS_PAYMENT_API_KEY,
}));

export default async function handler(req) {
  const result = await verify(req.body, req.headers);
  if (result.status === 'success') {
    // Fulfill the order with one shared shape.
  }
  return { statusCode: 200 };
}

Architecture

The flow is the same shape no matter which gateway you bolt on. The browser talks to a provider, the provider hands the user off to its checkout, and the gateway POSTs back to your webhook so the verifier can confirm payment and fulfill.

  1. 1

    Your UI

    Render any buy button you like.

  2. 2

    initiate()

    Core hands the order to the right provider.

  3. 3

    Checkout

    Gateway hosts payment; user completes it.

  4. 4

    Webhook

    Gateway POSTs to your verify endpoint.

  5. 5

    verify()

    Server core checks signatures, normalizes payload.

  6. 6

    Fulfill

    One shape. Unlock, ship, log, done.

For payments that take time to confirm like Monero block confirmations, for example, subscribeToStatus polls a tiny serverless endpoint until the webhook lands.

Packages

Every package follows the same shape. Browser providers expose initiate(); server providers expose a verifier and (where needed) a creator that holds gateway secrets.

@aquarian-metals/coin-moebius Browser

The browser core. createPaymentManager, register providers, initiate payments, listen for onSuccess / onPending / onError, and subscribe to long-running statuses.

@aquarian-metals/coin-moebius-server Server

The verifier core. registerVerifier and verify normalize gateway webhooks into one shared payment shape your fulfillment code can trust.

@aquarian-metals/coin-moebius-stripe Both

Reference Stripe provider. Browser entry initiates Stripe Checkout via your serverless session endpoint; server entry verifies Stripe webhook signatures.

@aquarian-metals/coin-moebius-monero-cryptomus Both

Reference Monero (Cryptomus) provider. Browser entry posts to your Cryptomus creator function; server entry verifies Cryptomus webhooks with Node crypto.

Example project

The fastest way to see Coin Moebius end to end is the static site demo. It ships a Vite front-end with Stripe and Cryptomus providers, the matching Netlify functions, and the webhook glue. Clone it, set the env vars, and you have a working checkout.

Safety

  • API keys for any provider that authorizes spend on your account stay on the server. The browser posts to a function you control.
  • Webhook handlers should always call verify() before doing fulfillment work — signature checks live in the verifier.
  • Treat the example’s supabase-schema.sql as a reference, not a turnkey database. Match it to your own data model.

Contribute

Gateway APIs change. The Stripe and Cryptomus packages are the reference implementations — we expect the community to bring everything else. Want Lightning, Solana, Zano, gold escrow, or a regional processor? Copy the template, write an initiate() and a verifier, publish it under your own scope.

Already shipping with Coin Moebius? Tell us and we will link to the things people are building.