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

# Custom code and upload

> Upload your own shop site — zip, folder or CLI — and connect it to shop data through the SDK.

Have your own project or a hand-written site? Upload it to ItemShop — you get a build, a preview, hosting on your shop's domain and shop data through the SDK. Every upload creates a new revision, so you can always go back to a previous version.

## Four ways to upload

**Zip**

**Workspace → Changes → Zip** — drop a `.zip` file or pick it from disk. The archive can be up to 25 MB (also unpacked), up to 5000 entries and 2000 project files; an entry compressed more than 200:1 is rejected. The project needs `itemshop.site.json` or `index.html` in the root. Paths are validated — entries escaping the project (`../`), absolute paths, `node_modules/` and `.git/` are rejected.

**CLI**

```bash theme={null}
npx itemshop login
npx itemshop deploy
```

Zips the project, uploads it as a revision, builds it and prints the preview address. Needs an API key with the `site:write` permission. Details: [CLI](https://andcze.mintlify.site/en/site/cli.md).

**GitHub**

**Workspace → Changes → GitHub → Connect GitHub** — install the ItemShop app on a repository, pick the repository and branch. Details below.

**API**

```bash theme={null}
curl -X POST "https://itemshop.dev/api/v2/shops/<shopId>/site/upload?message=my+change" \
  -H "X-API-Key: <key>" -H "Content-Type: application/zip" \
  --data-binary @site.zip
```

The response is the new revision. Limit: 20 uploads per 10 minutes.

After upload, ItemShop creates a revision → runs a build → deploys a **preview**. It reaches production only when you click **Publish** (or `itemshop deploy --prod`), unless you turned on auto-deploy from a git branch.

## GitHub

The integration uses a **GitHub App** — it gets access only to the repositories you pick, and only to contents (`Contents: read & write`). Uninstalling the app in GitHub disconnects Workspace automatically.

**1. Install the app**

**Workspace → Changes → GitHub → Connect GitHub** redirects to GitHub, where you choose the account and repositories.

**2. Pick a repository and branch**

Enter `owner/name` and the branch.

**3. Push and pull**

**Push draft** creates a commit on the branch, **Pull from GitHub** creates a new revision from the branch (author: `git`).

Sync rules:

* A **push** creates a single commit (fast-forward, no force). The branch becomes a **mirror of the site** — files that exist only in the repository disappear from the branch. The site is the source of truth; if you keep more in the repository, pull before editing.
* A **pull** accepts only regular files (no symlinks, submodules, `node_modules/` or `.git/`) and checks the [limits](https://andcze.mintlify.site/en/site/limits.md) before downloading content.
* **Auto-deploy from the branch** — a switch in **Changes → GitHub**: every push to the connected branch (webhook signed with HMAC) pulls files in the background and builds a preview. It reaches production only if you enable auto-deploy from a git branch in the [publishing rules](https://andcze.mintlify.site/en/site/workspace.md#publishing-rules) and turn off production approval.
* Pushes made by the platform itself are ignored, so there is no loop.

> [!NOTE]
>
> On installations without a configured GitHub App (self-hosting) the connection uses a fine-grained personal token with the *Contents* permission. Without the *Webhooks* permission, manual sync remains.

## The simplest site: plain HTML

No build, no npm — an `index.html` in the root is enough (a `static` project). Hosting enforces a strict CSP (`script-src 'self'`), so the script must be a separate file from your own origin — no inline scripts and no CDN libraries:

```html index.html theme={null}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>My shop</title>
  </head>
  <body>
    <ul id="products"></ul>
    <script type="module" src="/app.js"></script>
  </body>
</html>
```

```js app.js theme={null}
// window.__ITEMSHOP__ is injected by the builder: { shopId, apiBase, locale, buildId }
const { shopId, apiBase } = window.__ITEMSHOP__;
const res = await fetch(`${apiBase}/storefront/v1/shops/${shopId}/products`);
const { data } = await res.json();

document.querySelector("#products").innerHTML = data.products
  .map((p) => `<li>${p.name} — ${p.price} ${p.currency}</li>`)
  .join("");
```

Want the SDK in a `static` project? Upload its built ESM file with the site and import it from `/`. A project with a build is usually more convenient.

## A project with a build (Vite + React)

Add `itemshop.site.json` and use `@itemshop/sdk/react`:

```tsx src/App.tsx theme={null}
import { StorefrontProvider, useProducts, useCart } from "@itemshop/sdk/react";

function Products() {
  const { products } = useProducts();
  const cart = useCart();
  return products.map((p) => (
    <button key={p.id} onClick={() => cart.add(p)}>
      {p.name} — {p.price} {p.currency}
    </button>
  ));
}

export default function App() {
  return (
    <StorefrontProvider>
      <Products />
    </StorefrontProvider>
  );
}
```

Full API (checkout, discounts, widgets, error handling): [TypeScript SDK](https://andcze.mintlify.site/en/developers/sdk/typescript.md).

## Rules your site must follow

* **Static output only.** The site runs no server-side code. It fetches data in the browser from the [Storefront API](https://andcze.mintlify.site/en/developers/storefront-api.md).
* **Scripts only from your own origin.** The CSP allows scripts from the site's origin and `challenges.cloudflare.com` (Turnstile); `fetch` calls to your own origin and the platform API. Styles and fonts: own, Google Fonts; images over `https:`. Details: [Build & hosting](https://andcze.mintlify.site/en/site/build-hosting.md#site-security).
* **No secrets.** Do not put API keys in site files — everything you upload is public. The CLI skips `.env*`.
* **Payments through the ItemShop checkout.** `sf.checkout.create(...)` returns a `redirectUrl`; the site only redirects the player.
* **Consents at checkout.** The checkout form must collect acceptance of the terms and consent to immediate performance (loss of the right of withdrawal). Templates do this for you.
* **Forbidden files and scripts.** No `node_modules/`, `.git/`, `.npmrc`/`.yarnrc`/`.pnpmfile.cjs`; `package.json` must not have `preinstall`, `install`, `postinstall`, `prepare` etc. scripts.
* **Limits** on size and build time: [Limits](https://andcze.mintlify.site/en/site/limits.md).

## What the builder adds to your site

| Element | Contents |
| - | - |
| `window.__ITEMSHOP__` | `{ shopId, apiBase, locale, buildId }` — the SDK reads it automatically. Loaded from `/itemshop.config.js`, added at the start of `<head>` of every HTML file. |
| `/itemshop.data.json` | A snapshot of products from build time — for SEO and a fast first render. |

> **[CLI](https://andcze.mintlify.site/en/site/cli.md)**
>
> `init`, `dev`, `deploy`, `pull`.

> **[Build and hosting](https://andcze.mintlify.site/en/site/build-hosting.md)**
>
> How the site is built and where it runs.


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