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 rejectedlocalhost, *.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.