What is a BApp?

A BApp (Browser App) is a self-contained React component that lets a user generate some content — an image, SVG, HTML page, text, JSON, or any other inscription-ready format — and then inscribe it onto Bitcoin with one click.

You write the creative UI. Our BAppRuntime wraps it with:

  • A live content preview (image, HTML iframe, SVG, formatted JSON, etc.)
  • An Advanced Options panel (parent IDs, delegate, metadata, postage)
  • An Inscribe button that converts your output → NexusInscriberJson → Oodinals
  • Developer fee injection if your BApp definition specifies one

core rule

Your BApp calls onOutput() whenever the user creates or changes content. That's your only responsibility. Everything else — preview, advanced options, base64 encoding, payload building, inscription routing — is handled by the platform.

The output contract

When the user interacts with your BApp and produces content, call onOutput(output). The shape of BAppOutput is:

interface BAppOutput {
  // Required: the actual content to inscribe
  content: string | Blob;          // string for HTML/SVG/text/JSON; Blob for binary

  // Required: MIME type
  contentType: string;             // e.g. 'image/svg+xml', 'text/html;charset=utf-8'

  // Optional but recommended
  fileName?: string;               // e.g. 'my-art.svg'
  title?: string;                  // shown in the platform UI

  // Optional: human-readable preview
  preview?: string;                // data URI or object URL for images

  // Optional: inscription extras
  metadata?: Record<string, unknown>;   // merged into tag-5 CBOR metadata
  developerFee?: BAppDeveloperFee;      // override your catalog fee at runtime
  inscriptionDefaults?: {               // suggest defaults; user can override
    parentIds?: string[];
    delegateId?: string;
    metaprotocol?: string;
    postage?: number;
    contentEncoding?: 'br' | 'gzip' | 'deflate' | 'identity';
    compressBeforeInscribe?: boolean;
  };
}

Content types guide

content typecontent fieldpreview
image/svg+xmlstring (SVG markup)rendered as <img>
text/html;charset=utf-8string (HTML doc)sandboxed <iframe>
image/png / image/webpBlobrendered as <img>
application/jsonstring (JSON)formatted <pre>
text/plainstringtext <pre>

BAppProps & types

Every BApp component receives a single prop: onOutput.

// src/types/bapp.ts (already in the project)

interface BAppProps {
  onOutput: (output: BAppOutput | null) => void;
}

// Call onOutput(null) to clear the current output
// (e.g. when the user deletes their content)

Base template

Copy this template into src/components/bapp/apps/MyBApp.tsx and start customising.

'use client';

import { useState, useEffect } from 'react';
import type { BAppProps } from '@/types/bapp';

/**
 * MyBApp — replace this with your creative tool.
 *
 * Rules:
 *   1. Call onOutput() whenever content changes.
 *   2. Call onOutput(null) if the user clears their work.
 *   3. Do NOT implement an Inscribe button — the runtime adds it.
 *   4. Do NOT encode to base64 yourself — the runtime does it.
 */
export default function MyBApp({ onOutput }: BAppProps) {
  const [value, setValue] = useState('Hello, Bitcoin.');

  useEffect(() => {
    if (!value.trim()) {
      onOutput(null);
      return;
    }

    // Example: produce an SVG inscription
    const svg = `<svg xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 800 400" width="800" height="400">
  <rect width="800" height="400" fill="#0b0b0b"/>
  <text x="400" y="210"
    font-family="monospace" font-size="48"
    fill="#f7931a" text-anchor="middle"
    dominant-baseline="middle">${escXml(value)}</text>
</svg>`;

    onOutput({
      content: svg,
      contentType: 'image/svg+xml',
      fileName: 'my-inscription.svg',
      title: value.slice(0, 40),
    });
  }, [value, onOutput]);

  return (
    <div className="space-y-4">
      {/* Your tool UI goes here */}
      <label className="block">
        <span className="text-xs font-mono uppercase tracking-wide text-text-dim">Text</span>
        <input
          type="text"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          className="input-base w-full mt-1"
        />
      </label>
    </div>
  );
}

function escXml(s: string) {
  return s
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

Register your BApp

After creating your component, add it to the registry and catalog:

// 1. src/components/bapp/registry.tsx
//    Add a lazy import:
MyBApp: lazy(() => import('./apps/MyBApp')),


// 2. src/data/bapp-catalog.ts
//    Add an entry to the bapps array:
{
  id: 'my-bapp',
  slug: 'my-bapp',
  name: 'My BApp',
  description: 'Short description (1-2 sentences).',
  icon: '◇',                          // single character / emoji
  creatorName: 'YourName',
  creatorAddress: 'bc1p...',          // optional: your Bitcoin address
  category: 'Art',                    // see category guide below
  tags: ['tag1', 'tag2', 'tag3'],
  outputTypes: ['image/svg+xml'],
  launchType: 'component',
  launchComponent: 'MyBApp',          // must match registry key exactly
  status: 'beta',
  featured: false,
  version: '1.0.0',
  // Optional developer fee:
  monetisation: {
    hasDeveloperFee: true,
    feeAddress: 'bc1p...',
    feeAmountSats: 1000,
    feeMode: 'transaction',
  },
},

Submission checklist

How to submit

There are two ways to get your BApp into the store:

GitHub PR

Fastest path to production

Fork the public BApp repo, add your component, and open a PR. Once reviewed it goes live on the store.

  1. Forkgithub.com/switch-900/BappStore
  2. Buildfollow the template in /template
  3. PRopen a pull request with the BApp: prefix
View repo →
BApp Idea

Suggest a bounty

Have a great idea but can't code it? Open a GitHub issue describing what you want built. If the community picks it up and ships it, it goes in the store and they earn the dev fee.

Be specific — what it produces, what controls it needs, who it's for. Clearer specs get built faster.

Submit idea →

Category guide

ArtGenerative art, SVG patterns, algorithmic visuals. Output is typically SVG or PNG meant to be inscribed as-is.
HTML & WebHTML inscriptions, interactive web apps, cards, multi-page sites. Output is text/html.
ImageImage manipulation, pixel art, avatar/skin editors. Output is image/png, image/webp, etc.
3D3D model tools, lithophane generators, model compressors. Output is model/gltf-binary, model/stl.
UtilityDeveloper and creator utilities: QR generators, text tools, address tools. May or may not produce inscribable output.
CommunitySocial tools, registry browsers, collection viewers, community boards.
GamePlayable HTML games that produce inscription-ready interactive experiences.