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

# Build your own theme

> Build a code storefront by hand, from a blank look to a shop that sells, on the commerce layer the official templates share.

You do not need an AI agent to build a storefront, and you do not need to write the commerce parts. Every official template carries the same commerce layer; the look is the part you replace. This page is the by-hand version of that: what to keep, what to write, and how to know it works.

## Start from ForkMe

[ForkMe](/storefront/forkme) is the template built for this. Create a storefront from it under **Store → Storefronts → Advanced**, then pull it:

```bash theme={"system"}
shoppex storefront pull --dir ./my-theme
cd my-theme
bun install
```

Nova and Clean Minimal (Code) work the same way, but you would spend the first hour deleting a look you did not choose.

## What you keep

| Path | Why |
| - | - |
| `index.html` | Loads the Storefront SDK as a script. Never bundle it. |
| `vite.config.ts` | `base: './'` keeps assets working under the preview prefix. |
| `src/main.tsx` | The `<base href>` to router `basename` handoff, `CartProvider` around the app. |
| `@shoppexio/storefront-react` | The dependency in `package.json` that holds cart, checkout hand-off, catalog and product models, payload parsing, reviews, pages, menus, contact and the customer account with its translations. Its README maps every module. |
| `src/components/{product,catalog,cart,search,contact,reviews}/` | The commerce UI: variants, add-ons, custom fields, quotes, bundles. Restyle them, keep the hooks they call. |
| `src/pages/account-page.tsx` | Mounts the account from the package. |
| `src/preview-bridge.ts` | Click-to-select in the dashboard preview. |
| `public/shoppex.capabilities.json` | What the bundle declares it understands. |

## What you write

* **The look:** `src/theme/tokens.css`. Colours, type, radius, shadows, spacing. In ForkMe every Tailwind colour, font, size and radius utility maps to a token here, so a section cannot reach for a value outside the system.
* **The shell:** header, footer, page shell under `src/components/layout/`.
* **The home page:** sections under `src/sections/`, one file each, registered in `src/sections/index.tsx`.
* **The pages:** one file per route under `src/pages/`. Keep the routes the platform links to:

| Route | Page |
| - | - |
| `/` | Home |
| `/all-products`, `/products` | Catalog |
| `/product/:slug`, `/products/:slug` | Product |
| `/cart`, `/checkout` | Cart, checkout details |
| `/reviews`, `/feedback` | Reviews |
| `/contact`, `/support` | Contact |
| `/terms`, `/terms-of-service` | Terms |
| `/faq` | FAQ |
| `/page/:slug`, `/pages/:slug` | Merchant pages |
| `/dashboard/*`, `/customer-portal/*` | Customer account |
| `*` | Not found |

* **The content contract:** `src/config/content-defaults.json` is what a merchant edits in the Design tab; `content-schema.json` turns enums and bounds into pickers; `site-config.ts` parses both strictly. Every element that renders a content value carries `data-sx-config="<dotted.path>"`.

## How the data arrives

Nothing in a code storefront fetches the catalog. The edge injects `window.__SHOPPEX_INITIAL__` (shop, products, groups, categories, settings, the merchant's saved content) and the SDK bootstrap globals before the bundle runs, then the SDK on `window.shoppex` handles the live parts: cart, quotes, checkout, reviews, menus, pages, the account. `readStorefrontData()` from `@shoppexio/storefront-react` parses the payload once, strictly; a field that is missing throws instead of rendering a half shop. [Code storefront development](/storefront/code-storefront-development) lists the globals.

## The rules that are not yours to change

* `package.json` and the lockfile are fixed at build time; the build reinstalls them in a sandbox with no network. Add nothing you cannot ship inside the artifact.
* The SDK stays a `<script>` in `index.html`.
* `vite.config.ts` keeps `base: './'`.
* Reach the SDK through `getShoppex()` from the package, not `window.shoppex` directly: its first call captures the affiliate code from the URL, or affiliates stop earning.
* A new enum in a parser goes into `content-schema.json` in the same change, or a merchant can save a value that takes the storefront down.
* No placeholder data. A section with nothing real renders nothing.

## Prove it works

```bash theme={"system"}
bun run typecheck
bun run test
bun run build
shoppex storefront push
```

Then open the storefront preview under **Store → Storefronts** and walk the buyer's path: catalog, product with a variant and an add-on, add to cart, cart, checkout hand-off, reviews, contact, the account sign-in link, a wrong URL. Both colour schemes, one phone width.

ForkMe's tests are worth keeping as you go: the content schema stays in step with the parsers, the shipped defaults parse, the tokens file agrees with the defaults, and no literal colour sneaks into a section.

## When the commerce layer changes

ForkMe pins [`@shoppexio/storefront-react`](https://www.npmjs.com/package/@shoppexio/storefront-react) to an exact version, so nothing changes under you. To take a platform change, raise the version in `package.json`, run `bun install`, read the package's `CHANGELOG.md`, and run the typecheck and tests before you push. If you [ejected the account](/storefront/forkme#eject-the-account), port account changes by hand.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.