Skip to main content
A code storefront is a React and Vite project with a small commerce layer, one file for editable content, and a standard Vite build.
This page assumes a project already exists on disk. To get one, export a storefront or run shoppex storefront pull. See Code storefronts and the Theme CLI.

Import and export

Move a project in and out of Shoppex as a ZIP package.

Theme CLI

Pull, push, build, and deploy from the command line.

Project structure

Every official template shares this shape. File names inside commerce/ and config/ can differ between templates, but the folders and their purpose stay the same.

The commerce layer

src/commerce/ is where a storefront talks to Shoppex. It is not an npm package. Open package.json and no @shoppexio/* dependency appears there. index.html instead loads the Storefront SDK as a script, pinned to a version channel:
The browser exposes it as window.shoppex. src/commerce/shoppex.ts wraps that global with two functions: getShoppex() also runs the SDK’s one-time setup. It uses bootstrap globals a Shoppex worker injects next to the product catalog: shopSlug, shopId, apiBaseUrl, defaultCurrency, and an optional checkoutBaseUrl. A storefront without these globals cannot price a cart or check out, so getShoppex() fails fast instead of rendering with broken commerce. The catalog and the merchant’s content arrive the same way, read by src/config/site-config.ts: Neither function makes a network request. Both read window.__SHOPPEX_INITIAL__, injected by the same worker before the page renders. For cart and checkout, use the useCart hook from src/commerce/cart.tsx instead of calling the SDK directly. A component under CartProvider gets cart state and the actions that keep it, the SDK, and the current price quote in agreement:
useCart() returns lines, count, quote, and the actions add, update, remove, clear, applyCoupon, removeCoupon, and checkout. checkout calls the SDK’s checkout() and returns { success, message, code, redirectUrl, invoiceId }.
If a product has required checkout fields, collect them before calling checkout. resolveCheckoutFields(lines, products) and checkoutNeedsDetails(fields) in checkout-fields.ts tell you when a form must run first, and what to write onto the cart lines.
src/commerce/sdk.d.ts types the full window.shoppex surface this project uses. The complete method and type reference for the SDK lives at Storefront SDK reference.

Editable content: content-defaults.json

src/config/content-defaults.json is the template’s own text and settings: brand name, navigation links, hero copy, theme colors, cart labels, and the content for each page section. getSiteConfig() reads this file and merges the merchant’s saved content over it. The merge is a partial override: objects merge field by field, and arrays and single values replace completely. src/config/content-schema.json describes the field types in content-defaults.json. The Design tab then renders a color picker, a select, or a number field instead of raw text, for every value it can.
Without content-defaults.json, the Design tab has no fields to show. The storefront still works. Content edits then happen in Code or with AI instead of the Design tab.

Working locally

Every template runs on the same two commands.
bun run dev on its own renders no storefront. Every route shows a configuration error instead, because the store record and the SDK bootstrap globals have no local substitute. The values the app needs are these:

See it running with real data

Templates ship no local mock for these values on purpose, so a half-built shop never looks like a working one. Two paths reach real data:
  • Push and preview. Run shoppex storefront push to send your local project, then open the storefront under Store → Storefronts. This path needs no stub and matches production exactly.
  • Write your own stub. Serve a build with a static server, drop the cdn.shoppex.io script tag, and inject the globals above before the app runs. Keep the stub out of version control. Give every global a real value, not an empty string, and keep its synchronous methods, as typed in sdk.d.ts, returning values instead of promises.

What the build expects

Every code storefront builds the same way:
  • A build script in package.json
  • No network access while the script runs
  • Output in dist, out, or build, with an index.html at its root
See Code storefronts for the lockfile requirement and the full size limits.