Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt

Use this file to discover all available pages before exploring further.

App Manifest

Every LaunchMyStore app ships a single app.json file at the root of the app package. The manifest declares the app’s identity (handle, name, version) and every extension surface and function the app contributes. At install time the platform writes the manifest into public/extensions/{domainSlug}/{appHandle}/app.json per merchant. At render time the storefront, checkout, admin, and customer-account hosts read this file (through the local-manifest cache, 60s TTL) to discover which extensions and functions to load. If app.json is missing or unparseable, the app is silently skipped.
All keys under extensions are camelCase. Fields prefixed with _ (underscore) at any depth are reserved for tooling and ignored at install time.

Top-level fields

handle
string
required
Lowercase machine name for the app, e.g. product-reviews-pro. Must match the directory name under public/extensions/{domainSlug}/. Uniqueness is enforced per merchant.
name
string
required
Human-readable name shown in the merchant admin and the marketplace listing.
version
string
Semver version string (e.g. 1.4.2). Used by the versioning system to reconcile installed vs. published builds.
description
string
Short marketing copy displayed on the marketplace card and admin detail page.
iconUrl
string
Absolute URL to a square icon (PNG/SVG, recommended 256×256). Used by the customizer block picker and admin sidebar.
developer
string
Publisher name displayed on the marketplace listing.
developerUrl
string
Public website URL for the publisher.
appUrl
string
Base URL the merchant is redirected to after install completes (the app’s embedded admin entry point).
permissions
string[]
OAuth scopes the app requires (e.g. read_products, write_orders). See OAuth scopes.
extensions
object
Container for every extension/function the app contributes. See the per-key tables below.

Minimal example

{
  "handle": "my-app",
  "name": "My App",
  "version": "1.0.0",
  "extensions": {}
}

Extensions

The extensions object groups every extensible surface the app contributes. Every key is optional; an app can use as few or as many as it needs.
KeyTypePurposePage
storefrontBlocksarrayLiquid blocks merchants drop into theme sectionsTheme Blocks
storefrontSnippetsarrayReusable Liquid includes ({% render 'foo' %})Storefront Snippets
storefrontEmbedsarrayOverlay/floating scripts injected at <head> or before </body>Storefront Embeds
appScriptsarrayJS files auto-injected on every storefront pageApp Scripts
checkoutExtensionsarraySandboxed iframe at a named slot inside the React checkoutCheckout UI
postPurchaseExtensionsarrayIframe rendered on the order-success pagePost-Purchase
adminExtensionsarrayIframe embedded on admin resource detail pagesAdmin Blocks
adminActionsarrayButton on an admin resource page that opens a modal iframe (install-only — persisted as per-handle schema files)Admin Actions
printActionsarrayButton that opens a printable view (install-only — persisted as per-handle schema files)Admin Print Actions
customerAccountExtensionsarrayIframe blocks on the new customer-account pagesCustomer Account
webPixelsarraySandboxed customer-event listener scriptsWeb Pixels
posExtensionsarrayIframe extensions for the Point-of-Sale appPOS Extensions
functionsarrayDeclarative WASM functions (cart transform, discount, shipping, etc.)Functions Overview
orderRoutingRulesarrayJSON matchers that pick a fulfillment location at order placementOrder Routing
emailTemplatesarrayOverride transactional emails for named events (install-only)Email Templates
adminActions, printActions, and emailTemplates are accepted by the install endpoint but are not stored inline in app.json after install — they are persisted as per-handle schema files under admin-actions/, print-actions/, and email-templates/ respectively, and surfaced through the admin-extensions API.

storefrontBlocks

Liquid blocks merchants insert into theme sections via the customizer. Each entry produces a blocks/{handle}.aqua template and a blocks/{handle}.schema.json block schema.
"storefrontBlocks": [
  {
    "handle": "product-reviews",
    "title": "Product Reviews",
    "target": "product",
    "schema": {
      "name": "Product Reviews",
      "settings": [
        { "id": "limit", "type": "range", "min": 1, "max": 50, "default": 10, "label": "Reviews per page" }
      ]
    }
  }
]
FieldTypePurpose
handlestringRequired. Block machine name. Becomes the filename (blocks/{handle}.aqua).
titlestringDisplay label in the customizer block picker.
targetstringTemplate the block can be inserted into (product, index, collection, …).
schemaobjectStandard Shopify block schema (name, settings[], presets[]).
See Theme Blocks for the full block schema spec, supported setting types, and target reference.

storefrontSnippets

Reusable Liquid partials any theme block or section can {% render %}. Snippet handles share a single global namespace across all installed apps — the install endpoint logs a warning when two apps register the same handle and the filesystem-order winner is unpredictable. Prefix your handles with the app handle to be safe.
"storefrontSnippets": [
  { "handle": "my-app-stars", "description": "Renders a 5-star rating" }
]
FieldTypePurpose
handlestringRequired. {% render 'my-app-stars' %} invokes it.
descriptionstringOptional documentation displayed in the admin.

storefrontEmbeds

Overlay/floating scripts (chat widgets, cookie banners, A/B tools) injected at <head>, body, or compliance_head based on the target field. Merchants toggle each embed on/off in the customizer “App embeds” tray.
"storefrontEmbeds": [
  {
    "handle": "review-popup",
    "title": "Review Popup",
    "target": "body",
    "scriptSrc": "https://my-app.example.com/embed.js",
    "schema": { "name": "Review Popup", "settings": [] }
  }
]
FieldTypePurpose
handlestringRequired. Unique per app.
targetstringhead | body | compliance_head. Default body.
scriptSrcstringAbsolute URL to a JS file (loaded with <script defer>).
inlineHtmlstringAlternative to scriptSrc — raw HTML/CSS injected directly.
enabled_onobjectRestrict to specific templates/section groups: { templates: [], groups: [] }.
disabled_onobjectSame shape as enabled_on; exclusions win on conflict.
schemaobjectSettings schema for the customizer’s “App embeds” panel.
See Storefront Embeds for full schema and rendering behaviour.

appScripts

JavaScript files that the platform auto-injects on every storefront page render. Useful for installing pixels and chat widgets without editing the theme. The loadStrategy controls how the <script> tag is emitted: async (independent), defer (preserves order, runs after DOM), or idle (lowest priority via requestIdleCallback).
"appScripts": [
  {
    "handle": "loader",
    "src": "https://my-app.example.com/loader.js",
    "loadStrategy": "defer",
    "position": "head",
    "config": { "shopId": "auto" }
  }
]
FieldTypePurpose
srcstringRequired. Absolute URL to the script.
loadStrategystringasync | defer | idle. Default defer.
positionstringhead | body. Default body.
configobjectFree-form config passed via data-config attribute.
See App Scripts.

checkoutExtensions

Sandboxed iframes injected at named slots inside the React checkout. The host communicates with the iframe through App Bridge over postMessage.
"checkoutExtensions": [
  {
    "handle": "trust-badges",
    "target": "checkout-payment-after",
    "iframeUrl": "https://my-app.example.com/checkout/trust-badges.html",
    "settings": { "showCount": 4 }
  }
]
FieldTypePurpose
handlestringRequired. Unique per app.
targetstringRequired. Named slot — see Checkout UI targets.
iframeUrlstringURL loaded into the sandboxed iframe.
settingsobjectForwarded to the iframe via query string + App Bridge.

postPurchaseExtensions

Iframe rendered on the order-success page (e.g. one-click upsells). Smaller wired-action set than checkout — focused on order summary + upsell purchase.
"postPurchaseExtensions": [
  {
    "handle": "upsell",
    "target": "post-purchase",
    "iframeUrl": "https://my-app.example.com/postpurchase.html",
    "timeout": 60000
  }
]
FieldTypePurpose
handlestringRequired.
targetstringDefault post-purchase.
iframeUrlstringRequired. Iframe entry URL.
timeoutnumberMaximum render time in ms before the iframe is replaced with a skip. Default 60000.

adminExtensions

Iframes embedded inline on admin resource detail pages — product, order, customer, collection, discount, etc. The host (<AdminExtensionSlot target="…" />) fetches all extensions for a target and renders each in a sandboxed iframe.
"adminExtensions": [
  {
    "handle": "reviews-panel",
    "target": "product.details.block",
    "title": "Reviews",
    "url": "https://my-app.example.com/admin/reviews"
  }
]
FieldTypePurpose
handlestringRequired.
targetstringRequired. See Admin Block targets.
titlestringDisplayed in the admin panel header.
urlstringIframe URL (relative URLs are absolutized to the CustomerLMS origin).
iconUrlstringOptional icon for the panel header.
navigationLabelstringSidebar/tab label override.
permissionsobjectPer-target permission flags consumed by the host.

adminActions

Buttons on admin pages that open a modal iframe on click. Declared in the manifest but persisted to disk as admin-actions/{handle}.schema.json during install — the admin-extensions API merges them with adminExtensions and tags them with type: 'admin_action'.
"adminActions": [
  {
    "handle": "refund-tool",
    "target": "admin.order-details.action.render",
    "title": "Issue partial refund",
    "appUrl": "https://my-app.example.com/admin/refund",
    "icon": "https://my-app.example.com/icons/refund.svg"
  }
]

printActions

Buttons that open a printable view in a new window. Manifest carries either a Liquid template (rendered server-side) or an appUrl (iframe).
"printActions": [
  {
    "handle": "packing-slip",
    "target": "admin.order-details.print.render",
    "title": "Packing slip",
    "template": "{{ order.name }} — {{ order.line_items | size }} items"
  }
]

customerAccountExtensions

Iframe blocks rendered on the new customer-account pages (order status, dashboard, profile, order list). Same iframe contract as checkout extensions — bearer-token gated.
"customerAccountExtensions": [
  {
    "handle": "review-prompt",
    "target": "customer-account.order-status.block.render",
    "iframeUrl": "https://my-app.example.com/account/review-prompt.html",
    "permissions": ["read_orders"]
  }
]
See Customer Account for the full target list.

webPixels

Sandboxed customer-event listener scripts loaded into an isolated iframe. Subscribe to events like page_viewed, cart_updated, checkout_completed. The manifest accepts either a remote scriptSrc URL or an inlineScript string which the installer writes to web-pixels/{handle}.js.
"webPixels": [
  {
    "handle": "review-prompt-pixel",
    "scriptSrc": "https://my-app.example.com/web-pixel.js",
    "events": ["checkout_completed"],
    "settings": { "delay": 5000 },
    "permissions": ["customer_email"]
  }
]
See Web Pixels.

posExtensions

Iframe extensions for the Point-of-Sale app. Same shape as adminExtensions; targets start with pos.. The admin-extensions API tags these with type: 'pos_extension' so the POS host can fork rendering from regular admin blocks.
"posExtensions": [
  {
    "handle": "loyalty-lookup",
    "target": "pos.checkout.block.render",
    "title": "Loyalty",
    "url": "https://my-app.example.com/pos/loyalty"
  }
]
See POS Extensions.

functions

Declarative WASM functions that fire in the cart → checkout → order-placement pipeline. Each entry maps to one of the nine supported function types. The install endpoint validates type, handle, inputFields, and network_access / allowed_hosts and rejects the install on any violation.
"functions": [
  {
    "type": "discount",
    "handle": "tiered-discount",
    "title": "Tiered Volume Discount",
    "entrypoint": "dist/discount.wasm",
    "inputFields": {
      "cart": { "lines": { "id": true, "quantity": true, "merchandise": { "price": true } } }
    },
    "network_access": false
  }
]
FieldTypePurpose
typestringRequired. One of the 9 function types.
handlestringRequired. Unique per app.
titlestringDisplay name shown to the merchant.
entrypointstringRelative path to the compiled WASM module (uploaded separately).
inputFieldsobjectSubtree projection of the REST input — see Input fields.
network_accessbooleanOpt in to outbound fetch_url. Requires allowed_hosts.
allowed_hostsstring[]Non-empty list of hostnames the function may call. Validated at install.
Function active-install caps apply per shop, per type — see Function active limits. Installs over the cap fail with HTTP 409.

orderRoutingRules

Declarative matchers that select a fulfillment location at order placement. Internally flattened into the functions dispatch list as type fulfillment_location_rule.
"orderRoutingRules": [
  {
    "handle": "us-east-warehouse",
    "title": "Route US-East orders to NYC warehouse",
    "entrypoint": "rules/us-east.json"
  }
]
See Order Routing.

emailTemplates

Per-event transactional email overrides. Each entry replaces the default template for one event (order_confirmation, shipping_confirmation, etc.).
"emailTemplates": [
  {
    "event": "order_confirmation",
    "subject": "Thanks for your order, {{ customer.first_name }}!",
    "htmlBody": "<h1>Order {{ order.name }}</h1>...",
    "enabled": true
  }
]
The authoritative copy of the email template is stored in the backend EmailTemplate table — the install endpoint also writes a debug preview to email-templates/{event}.json on disk.
See Email Templates.

Validation rules

The install endpoint (POST /api/apps/install-extensions) enforces the following at install time. Failures return HTTP 400.
Within a single app.json, every handle inside one extension array must be unique. Across apps, snippet handles (storefrontSnippets) share a global namespace per merchant — collisions are logged but do not fail the install.
Every entry under functions must have:
  • typecart_transform, discount, shipping_rate, payment_customization, delivery_customization, order_validation, fulfillment_constraints, local_pickup_options, pickup_point_options
  • A non-empty handle string
  • Valid inputFields (every leaf is true/false, internal nodes are plain objects) if present
  • When network_access: true, a non-empty allowed_hosts array of valid hostnames (no scheme, no path)
The backend installApp() checks the merchant’s currently active apps for each function type. If installing this app would push the count over the per-type cap, install fails with HTTP 409. See Function active limits for the per-type caps.
target strings on checkoutExtensions, adminExtensions, posExtensions, customerAccountExtensions, and adminActions/printActions are not validated against a closed enum — but unknown targets simply won’t be picked up by any host. Refer to the target lists on the relevant extension pages.
Snippet handles share one Liquid resolver namespace across all apps on a merchant. Installation continues on conflict but logs a warning and render order is filesystem-dependent. Prefix snippet handles with the app handle to avoid clashes.
Directories under public/extensions/{domainSlug}/ whose name starts with _ (underscore) are ignored at manifest read time and can be used for scratch / debug data.

Full example

{
  "handle": "product-reviews-pro",
  "name": "Product Reviews Pro",
  "version": "2.1.0",
  "description": "Verified product reviews with photo support.",
  "iconUrl": "https://reviews.example.com/icon.png",
  "developer": "Example Inc.",
  "developerUrl": "https://example.com",
  "appUrl": "https://reviews.example.com/admin",
  "permissions": ["read_products", "write_metafields"],
  "extensions": {
    "storefrontBlocks": [
      {
        "handle": "review-widget",
        "title": "Review Widget",
        "target": "product",
        "schema": {
          "name": "Reviews",
          "settings": [
            { "id": "limit", "type": "number", "default": 10, "label": "Reviews per page" }
          ]
        }
      }
    ],
    "storefrontSnippets": [
      { "handle": "reviews-pro-stars" }
    ],
    "appScripts": [
      { "src": "https://reviews.example.com/loader.js", "loadStrategy": "defer" }
    ],
    "adminExtensions": [
      {
        "handle": "reviews-panel",
        "target": "product.details.block",
        "title": "Reviews",
        "url": "https://reviews.example.com/admin/reviews"
      }
    ],
    "webPixels": [
      { "handle": "review-prompt", "scriptSrc": "https://reviews.example.com/pixel.js", "events": ["checkout_completed"] }
    ],
    "functions": [
      {
        "type": "discount",
        "handle": "reviewer-discount",
        "title": "5% off for reviewers",
        "entrypoint": "dist/discount.wasm"
      }
    ],
    "emailTemplates": [
      {
        "event": "order_confirmation",
        "subject": "Don't forget to review your order!",
        "htmlBody": "<p>...</p>"
      }
    ]
  }
}

See also

Extensions Overview

Every extension surface in one place.

Functions Overview

Declarative WASM functions for cart, shipping, discounts, validation.

App Types & Tiers

Public / private / first-party and the four pricing tiers.

App Lifecycle

Install, update, uninstall, and the version reconciliation pipeline.