Mini-apps#

A mini-app is an ordinary web page you host, opened inside a Mafold conversation. It gets a signed identity for the current user, a realtime document shared with everyone in the chat, and panel chrome — through a single global, window.Mafold.

If you've built a Telegram Mini App, the shape will feel familiar: you own the URL and the code; Mafold provides the host, the identity handshake, and the capabilities.

The one-line version

Ship a URL, add the @mafold/webapp SDK, register the app to get a signing secret. Mafold opens your page in a panel, hands it a verifiable identity token, and gives every open copy a shared realtime room.

The mental model#

Your page

A mini-app is your web app on your hosting (or free Mafold hosting). Mafold never runs your code — it loads your URL in a sandboxed panel and talks to it over a message bridge.

Identity, verified

On launch, Mafold hands your page a short-lived signed token (initData, a JWT). Send it to your backend and verify it with your app secret — that's how you trust who is using the app. See Authentication.

A shared room

Every conversation an app is open in has one shared room — a realtime document (a CRDT). Anyone can read and write it; changes converge and broadcast live. This is how you build multiplayer: a counter, a poll, a game board. See the SDK reference.

Embedded vs standalone#

The same build runs in two modes, and the SDK abstracts the difference:

EmbeddedStandalone
Openedinside a Mafold chat panelyour URL, directly in a browser
Identityinstant, from the signed launch tokenMafold.auth() → Login with Mafold (PKCE)
room.*over the host bridgetransparently over Mafold's HTTP API
chat.*availablerejects with { code: "not_embedded" }

Mafold.embedded tells you which mode you're in. You rarely need to branch on it — auth() and room.* do the right thing automatically; only chat-only features (sendMessage, reading the thread) require the embedded host.

Add the SDK#

Two ways to include it — same Mafold object either way.

<!-- 1) Versioned script tag (immutable-cached) -->
<script src="https://mafold.com/js/mafold-webapp@0.3.0.js"></script>
// 2) npm — ships TypeScript types
import Mafold from "@mafold/webapp";

Minimal app#

Mafold.ready();                              // tell the host the UI is up

const user = Mafold.initDataUnsafe?.user;    // display-only identity (unverified)
document.querySelector("#hi").textContent = `Hi, ${user?.display_name}`;

await Mafold.room.open();                     // the conversation-shared document
Mafold.room.onUpdate((doc) => render(doc));   // re-render on any participant's change
await Mafold.room.increment("taps");          // everyone sees it, live

That's a complete multiplayer app: every person who opens it in the same chat shares the taps counter, and each tap broadcasts to all of them.

Test locally

Point your app at the launch harness at mafold.com/harness — it mints a dev launch token and opens your local URL as if it were embedded, so you can develop against the real bridge without publishing.

Next steps#