> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shoppex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Code storefront development

> The folder structure, the commerce layer, and how to work locally in an Advanced storefront project.

A code storefront is a React and Vite project with a small commerce layer, one file for editable content, and a standard Vite build.

<Note>
  This page assumes a project already exists on disk. To get one, export a storefront or run `shoppex storefront pull`. See [Code storefronts](/storefront/code-storefronts) and the [Theme CLI](/storefront/theme-cli).
</Note>

<CardGroup cols={2}>
  <Card title="Import and export" icon="download" href="/storefront/code-storefronts">
    Move a project in and out of Shoppex as a ZIP package.
  </Card>

  <Card title="Theme CLI" icon="terminal" href="/storefront/theme-cli">
    Pull, push, build, and deploy from the command line.
  </Card>
</CardGroup>

## 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.

```
.
├── index.html                    Loads the Shoppex SDK script and mounts the app
├── package.json                  Scripts and dependencies
├── vite.config.ts                Build config
├── src/
│   ├── main.tsx                   React root, wraps the app in CartProvider
│   ├── App.tsx                    Routes and page layout
│   ├── commerce/                  The commerce layer, see below
│   │   ├── shoppex.ts              Wraps window.shoppex and the bootstrap globals
│   │   ├── sdk.d.ts                Types for window.shoppex
│   │   ├── cart.tsx                CartProvider and the useCart hook
│   │   └── checkout-fields.ts      Custom checkout fields per product
│   ├── config/
│   │   ├── site-config.ts          Reads the catalog and the merchant's content
│   │   ├── content-defaults.json   Default content for the Design tab, see below
│   │   └── content-schema.json     Field types the Design tab renders
│   ├── components/                 Page sections and UI
│   └── styles/                     CSS
└── tests/                          Optional unit tests for commerce logic
```

## 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:

```html theme={"system"}
<script src="https://cdn.shoppex.io/sdk/v1.0/shoppex.umd.js"></script>
```

The browser exposes it as `window.shoppex`. `src/commerce/shoppex.ts` wraps that global with two functions:

| Function             | Returns                                                                                               |
| -------------------- | ----------------------------------------------------------------------------------------------------- |
| `getShoppex()`       | The initialized SDK. Throws if the script did not load, or if a required bootstrap global is missing. |
| `getBuyerCurrency()` | The currency the injected prices use.                                                                 |

`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`:

| Function          | Returns                                                                                     |
| ----------------- | ------------------------------------------------------------------------------------------- |
| `getProducts()`   | The shop's catalog, as an array of products with price, stock, variants, and custom fields. |
| `getSiteConfig()` | The merchant's content, merged over `content-defaults.json`.                                |

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:

```tsx theme={"system"}
import { useCart } from './commerce/cart';

function AddToCartButton({ product }: { product: StorefrontProduct }) {
  const { add } = useCart();
  return <button onClick={() => add(product, null, 1)}>Add to cart</button>;
}
```

`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 }`.

<Note>
  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.
</Note>

`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](/developers/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.

<Note>
  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.
</Note>

## Working locally

Every template runs on the same two commands.

```bash theme={"system"}
bun install
bun run dev     # starts the Vite dev server, default http://localhost:5173
bun run build   # writes dist/index.html and hashed assets
```

`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:

| Global                       | Type             | Holds                                            |
| ---------------------------- | ---------------- | ------------------------------------------------ |
| `window.shopSlug`            | string           | The shop's slug                                  |
| `window.shopId`              | string           | The shop's id                                    |
| `window.apiBaseUrl`          | string           | The base URL for the Shoppex API                 |
| `window.defaultCurrency`     | string           | The currency the injected prices use             |
| `window.checkoutBaseUrl`     | string, optional | The base URL for Hosted Checkout                 |
| `window.__SHOPPEX_INITIAL__` | object           | The store record and the product catalog         |
| `window.shoppex`             | object           | The SDK itself, matching `src/commerce/sdk.d.ts` |

### 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](/storefront/code-storefronts) for the lockfile requirement and the full size limits.
