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

# Import and Export Advanced Storefronts

> Move an Advanced storefront in and out of Shoppex as a portable ZIP package.

# Import and Export Advanced Storefronts

An Advanced storefront is a React and Vite project you own. Shoppex packages it
as a ZIP so you can keep a backup, hand the project to someone else, work on it
locally, or bring an existing project in as a new storefront.

Easy (visual) themes are not part of this page. They export as ThemeDocument
JSON instead — see [Editing Themes](/themes/editing).

<CardGroup cols={2}>
  <Card title="Export" icon="download">
    Download the current source tree plus a package manifest as one ZIP.
  </Card>

  <Card title="Import" icon="upload">
    Upload a ZIP as a brand new storefront, or replace the source of an
    existing one.
  </Card>
</CardGroup>

## Export a storefront

There are three ways to get the ZIP, and all three produce the same archive:

* **From the storefront list** — open **Store → Storefronts**, switch to
  **Advanced**, and choose **Download source ZIP** from a storefront card's
  menu.
* **From the code editor** — open the storefront and use the **Download**
  action in the toolbar.
* **From the CLI** — run `shoppex storefront export`. See the
  [Theme CLI Reference](/themes/cli-reference) for flags and authentication.

The export always describes one moment: the file list, the source revision, and
your Design content are read together, so the archive is never a mix of two
revisions. The downloaded file is named after that revision
(`storefront-source-8f1c4a90d2b7.zip`).

## What the ZIP contains

The archive holds your complete source tree for the current revision, plus one
extra file at the archive root: `shoppex.theme.json`, the package manifest.

```json theme={"system"}
{
  "manifest_version": 1,
  "kind": "code-storefront",
  "name": "My React Store",
  "theme_version": "1.0.0",
  "code_template": "nova",
  "source_revision": "8f1c4a90d2b73e55",
  "exported_at": "2026-08-01T09:41:12.503Z",
  "content": {
    "hero": { "headline": "Summer drop" }
  }
}
```

`content` is what you edited in the **Design** tab — the draft when one exists,
otherwise the published copy, and `null` when the storefront still runs on the
defaults shipped in its files.

<Info>
  `shoppex.theme.json` is metadata, not source. Shoppex adds it to the ZIP on
  export and consumes it on import, and you cannot create a source file with
  that name — the name is reserved.
</Info>

### The round-trip promise

* **Import** applies the manifest's `content`. Export a storefront, import the
  ZIP, and your Design content comes back with it instead of falling back to
  the template defaults.
* **Replace** never applies it. The storefront you are replacing already owns
  its own Design content, and a source swap must not silently overwrite it. The
  response tells you when a package carried content that was not applied.
* `code_template` is provenance for humans only. It is never restored onto the
  imported storefront, so a paid template stays a purchase and cannot travel in
  an archive.

## Import a ZIP as a new storefront

Open **Store → Storefronts**, switch to **Advanced**, and use **Import ZIP**.
Give the storefront a name, drop in the archive, and Shoppex creates it and
starts the first build immediately.

The archive must satisfy these:

| Requirement           | Limit                                       |
| --------------------- | ------------------------------------------- |
| Uploaded ZIP          | 42 MiB                                      |
| Extracted source tree | 40 MiB                                      |
| Files                 | 400                                         |
| Single file           | 5 MiB                                       |
| Path length           | 512 characters                              |
| Root `package.json`   | Required, with a non-empty `"build"` script |

Also true of every accepted archive:

* Symbolic links are rejected, and so are absolute paths or paths containing
  `..`.
* Paths that collide only by letter case (`Header.tsx` and `header.tsx`) are
  rejected.
* If everything sits inside a single top-level folder, that folder is stripped,
  so zipping a project directory works as expected.
* These are dropped before anything is stored: `__MACOSX`, `.git`,
  `node_modules`, `dist`, `.turbo`, `.shoppex`, and any `.DS_Store`.
* A `shoppex.theme.json` at the root is consumed as the package manifest. If it
  is present but not a valid manifest, the import fails rather than quietly
  importing just the files.

### The Design tab

If the archive ships `src/config/content-defaults.json`, the **Design** tab in
the editor has fields to edit and the import opens the editor directly. An
archive without it is still a perfectly valid storefront — the import just tells
you the Design tab will be empty, and you edit in **Code** or with AI instead.

## Replace the source of an existing storefront

Open the storefront in the editor and use **Replace Source from ZIP**. Every
current file is deleted and replaced by the contents of the archive.

<Warning>
  A replace is destructive and covers the whole tree. Download the current
  source first if you want to keep a copy, and save or discard unsaved editor
  changes — they only exist in your browser.
</Warning>

A replace is guarded by the source revision you loaded. If someone else — or an
AI edit, or a CLI push — saved in the meantime, the upload is rejected with a
conflict instead of overwriting their work. Reload the storefront and try again.

The replace uploads the tree; it does not build. The dialog starts a build for
you right after, and you can always press **Build** yourself.

The CLI covers the same ground for a local checkout: `shoppex storefront push`
sends your working copy under the same revision guard and enqueues the build.
See the [Theme CLI Reference](/themes/cli-reference).

## What the build expects

Every import and every replace ends in the same pipeline: install, build,
collect the output, upload it as an immutable artifact.

* Dependencies are installed from your lockfile with lifecycle scripts
  disabled. Commit `bun.lock` or `bun.lockb` for a reproducible, frozen install.
* Your `build` script runs in a sandbox with **no network access**. Anything it
  needs must already be in the project or its dependencies.
* The output must land in `dist`, `out`, or `build`, and must contain
  `index.html`.
* The finished artifact is capped at 200 MB and 20,000 files.

A build that fails leaves the currently published storefront untouched. Only
publishing changes what visitors see.
