Prebit Developer Docs

Publishing & Manifest

prebit.app.toml, full reference, and how a submission is reviewed.

A submission is a manifest (prebit.app.toml) + extension assets (templates/CSS/sandboxed JS, if you have any) + screenshots + policy URLs. Your backend source is never part of it — it never runs on Prebit's infrastructure, so it isn't relevant to review.

Full manifest reference

manifest_version = 1
minimum_platform = "1.0"
runtime          = "v1"   # sandboxed extension-runtime version — versioned
                          # independently of minimum_platform
name             = "Reviews"
version          = "1.2.0"
developer_org    = "acme-labs"

permissions  = ["read_products", "read_customer_pii"]
capabilities = ["can_write_extension_storage", "can_use_billing_api"]

blocks   = ["review-widget", "rating-stars"]    # app_block — not built yet
embeds   = ["review-popup"]                      # app_embed — Extension Runtime
webhooks = ["order.created", "product.deleted"]  # delivered to YOUR server

background_jobs = [{ id = "sync-reviews", capability = "can_register_background_job" }]
scheduled_jobs  = [{ id = "nightly-import", cron = "0 2 * * *" }]

network_origins = ["https://api.reviews-acme.com"]  # sandbox connect-src allowlist ONLY

billing = "prebit"        # or "external"
price   = 299

[compatibility]
platform = ">=1.0"
runtime  = ">=1.0"
theme    = ">=2.0"
sdk      = ">=0.1.0"      # informational — @prebit/sdk version this was built against
cli      = ">=0.1.0"      # informational — prebit-cli version this was built against

[performance_budget]
bundle_kb = 150
css_kb    = 30

Field reference

FieldNotes
manifest_versionMust be 1
name1–80 chars
versionMust be semver x.y.z
permissionsFree-form strings today — scopes/capabilities aren't cross-validated against a fixed enum for permissions
capabilitiesMust be one of the known capability strings — see Authentication
blocks / embedsNon-empty identifiers. blocks isn't usable yet (app_block not built)
webhooksShort topic names — see Webhooks for the mapping
network_originsEach entry must be a safe public https:// origin — a connect-src allowlist only, never an executable-script allowlist
billing"external" (default) or "prebit" — see Billing
priceRequired, must be positive, if billing = "prebit"
compatibility.sdk / .cliInformational today — not enforced by the review scanner, but a template/tool can warn on a mismatch

network_origins is a sandbox fetch-destination allowlist ONLY. It is never treated as permission to load executable JavaScript from that origin — every reviewed extension asset must be self-contained. See Review Process.

Submitting

prebit build .      # parses + scans locally, stages dist/
prebit publish .    # re-checks, then submits

The submission runs the full automated scan synchronously — a submission with any blocking error is rejected outright, never stored as "pending." See Review Process for exactly what's checked. A successful submission still needs manual review (permissions, screenshots, pricing) before it can be approved and installed by merchants.

Versioning

Every AppRelease is immutable — a version can't be edited in place, only superseded by a new submission with a higher semver version. Submitting the same version twice is rejected (409).

Signing (optional until your org registers a key)

If your DeveloperOrganization has registered a publisher signing key, every submission must include a valid publisherSignature or it's rejected. Orgs without a registered key yet skip this check.

import { buildReleaseSignaturePayload, signPayload } from "@prebit/sdk";
import crypto from "crypto";

const manifestHash = crypto.createHash("sha256").update(manifestToml, "utf8").digest("hex");
const payload = buildReleaseSignaturePayload(manifestHash, assetContentHashes);
const publisherSignature = signPayload(privateKeyPem, payload);

prebit publish --private-key <path> does this for you.

On this page