AppbrewDevelopers
Build
For partner devs

Build an integration

Create an integration package from scaffold to manifest.

An integration is an npm package that plugs your service into Appbrew apps. You develop it inside your app repo as a local workspace package, and it ships to merchants as a normal dependency.

Scaffold

From your app repo root:

pnpm create-integration my-integration
pnpm install

This creates the package and links it into the workspace:

package.json
index.ts

Because the app consumes it as a workspace:* dependency, every edit under packages/my-integration/src/ hot-reloads in the running app, with no build or publish step during development. Import it by package name, exactly as consumers will after it is published:

import { MyBlock } from 'my-integration'

Package requirements

Appbrew apps compile integration packages from TypeScript source at build time, so the package must ship source, not a bundle:

  • main and types point at src/index.ts
  • files lists ["src/"]
  • Every @gauntlet/* package you import is a peer dependency — the host app provides it; never bundle it. Same for native modules your integration needs (e.g. react-native-webview).
  • Export everything through src/index.ts; it is the package's only entry point.

The scaffold generates a package.json that already satisfies this shape (including the baseline peer dependency and publish metadata); keep it intact as you add your own peer dependencies.

What an integration can ship

Three things, and most packages combine at least two:

  1. Blocks — UI components merchants place on screens, exported together with a register{Name}Blocks function.
  2. An analytics tracker — a class that forwards app events to your platform. See Analytics trackers.
  3. A manifest — an appbrew key in package.json that tells the platform what your integration is and what merchants configure.

Blocks and the register function

Blocks inside a package are written exactly like custom blocks; only the registration differs. Export one function that registers all of them:

packages/my-integration/src/register.ts
import { ReviewsCarousel } from './blocks/reviews-carousel'
import { ReviewsBadge } from './blocks/reviews-badge'

export function registerMyIntegrationBlocks(r: Map<string, any>) {
  r.set('my-integration-reviews-carousel', ReviewsCarousel)
  r.set('my-integration-reviews-badge', ReviewsBadge)
}

Prefix block ids with your integration name. Ids share one registry with every other package the app installs.

The manifest

The appbrew key declares the merchant-facing settings, the key your code reads config under, and whether installing the integration requires a native rebuild (true whenever you add native modules; false for pure-JS packages):

packages/my-integration/package.json
{
  "name": "my-integration",
  "version": "1.0.0",
  "main": "src/index.ts",
  "types": "src/index.ts",
  "files": ["src/"],
  "peerDependencies": {
    "@gauntlet/analytics": "*",
    "@gauntlet/state": "*",
    "@gauntlet/types": "*",
    "@gauntlet/ui-builder": "*"
  },
  "appbrew": {
    "configKey": "my-integration",
    "requiresNativeBuild": false,
    "settings": [
      { "key": "apiKey", "title": "API key" },
      { "key": "merchantId", "title": "Merchant ID", "placeholder": "Enter Merchant ID" },
      { "key": "enableBadges", "title": "Show review badges", "type": "boolean" }
    ]
  }
}

What merchants enter under settings lands in the app config under your configKey, at integrations["my-integration"], where your blocks and tracker read it. The full field reference lives in the manifest schema.

Wire it into the app

Register your blocks in the app's registration file. Packages keep exporting register{Name}Blocks so hosts on any platform version can consume them; on 0.27.0 and later the host can wire the same blocks through app.components.register on the app extension host from @gauntlet/brewery.

src/app/register-blocks.ts
import { app } from '@gauntlet/brewery'
import { ReviewsBadge, ReviewsCarousel } from 'my-integration'

app.components.register('block', 'my-integration-reviews-carousel', ReviewsCarousel)
app.components.register('block', 'my-integration-reviews-badge', ReviewsBadge)

Returns an undo, and the same call registers screens, icons, and product cards — see Extending app behavior.

Trackers are wired in src/app/App.tsx; Analytics trackers covers that half.

Next

On this page