Automated Checks & Compliance

Every submission is validated before it reaches a human reviewer. A failure is a hard 400 with a list of { code, severity, message } — nothing is stored, so fix and resubmit.

App submission checks

Field rules

Check Rule
Name Required, non-blank, ≤ 120 characters
Description ≤ 5000 characters
Slug Must match ^[a-z][a-z0-9-]{1,60}$ (derived from your name if you don't control it)
Version Must be semver — ^\d+\.\d+\.\d+([-+].+)?$, e.g. 1.0.0, 2.1.0-beta
App URL Required — an external-hosted app has to say where it lives
Tags Must be an array, ≤ 20 tags, each ≤ 40 characters
Screenshots ≤ 12, each URL safety-checked
Price ≥ 0

There are no warning-level rules for apps. Everything above either passes or blocks the submission.

URL safety (anti-SSRF)

Applied to App URL, Redirect URL, Webhooks URL and the logo URL:

  • Must parse as a URL.
  • HTTPS only. Plain http: is rejected, which also blocks javascript: and data: payloads.
  • Numeric-encoded hosts rejected — hex (0x…), all-digit (2130706433), and leading-zero octal forms.
  • Private and internal hosts rejected — localhost, *.local, *.internal, 127.*, 10.*, 192.168.*, 172.16–31.*, 169.254.*, CGNAT 100.64/10, 0.0.0.0, and IPv6 ::*, fc*, fd*, fe80*.

The host is checked again with DNS resolution at webhook delivery time, so a public hostname that resolves to a private address will still fail later.

Allowlists

Unknown values are rejected outright — they are not ignored.

Permissions (11)

read_orders    write_orders
read_products  write_products
read_customers write_customers
read_inventory write_inventory
read_analytics read_shop
manage_webhooks

Events you may subscribe to (9)

order.created   order.paid       order.fulfilled  order.cancelled
product.created product.updated
customer.created
app.installed   app.uninstalled

ui_slots (6, phase-2 metadata only — nothing renders them)

storefront.product.below_price
storefront.product.below_add_to_cart
storefront.cart.footer
dashboard.order.detail.sidebar
dashboard.product.detail.sidebar
dashboard.nav.section

Slug ownership

A slug belongs to the developer who first published it. Submitting an app whose slug is already owned by someone else fails with 409 — "The app identifier is already in use by another developer." Resubmitting your own slug is an in-place version update.

Theme package checks

The ZIP is validated on upload, before it is stored.

Check Rule
Archive Must be a readable ZIP. Upload limit 50 MB
Manifest theme.config.json must exist and be valid JSON
Manifest fields name, slug, version, author all required
Slug ^[a-z][a-z0-9-]{1,40}$ — note this is stricter than the app slug rule
Reserved slugs Cannot be default, grid, manfare or general
Structure A theme/ directory is required
Components All nine required: index.ts, header.tsx, footer.tsx, product-card.tsx, single-product-page.tsx, category-page.tsx, cart-page.tsx, checkout-page.tsx, search-page.tsx
Templates theme/templates/<type>.json must be valid JSON, <type> must be a known system page type, and every widget/section name must resolve — either to a platform registry entry or to your own x-<slug>-* namespace
Custom widgets Each widget directory must be namespaced x-<slug>-* and contain a widget.json

Content and code safety

Rejected in template strings: inline <script>, eval(, javascript:, inline on*= handlers, srcdoc=.

Rejected in .ts / .tsx sources: Node built-in imports or requires, eval(, new Function(.

Warning only (does not block): dangerouslySetInnerHTML. It is allowed, but you own the sanitisation.

After upload an advisory security scan runs asynchronously. It never blocks the submission and never changes review status — it is information for the reviewer.

Run npm run validate in the preset kit before packaging; it catches most of this locally.

What the platform does not check

Nothing here is enforced, so do not assume it is covered:

  • No TLS certificate validation at review time beyond requiring https.
  • No install-flow smoke test. Nobody clicks through your app automatically.
  • No compliance webhooks. GDPR-style customer/shop data request and erasure webhooks do not exist on this platform.
  • No embedded-app conformance checks — there is no App Bridge and no session token scheme to conform to.
  • No uptime or performance monitoring of your hosted service.

See Compliance & Preliminary Steps for the pre-submit checklist.