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

# Quickstart

> Build a theme, render it locally, and deploy it from GitHub.

A theme with one editable section, rendered locally and deployed to a store.

## Install the CLI

<Steps>
  <Step title="Install Slurp">
    ```bash theme={null}
    cargo install slurp-compiler slurp-dev-server
    ```

    This installs two binaries: `slurp` for build and validate, and `slurp-dev`
    for the preview server.

    ```bash theme={null}
    slurp --version
    ```
  </Step>
</Steps>

## Create the theme

<Steps>
  <Step title="Create the directories">
    ```bash theme={null}
    mkdir -p my-theme/site/{pages,layouts,sections,templates,css}
    cd my-theme
    ```

    `site/` is the theme root. The parent directory holds build tooling, which
    is not published.
  </Step>

  <Step title="Write the manifest">
    `site/theme.json` identifies the directory as a ByteSell theme.

    ```json site/theme.json theme={null}
    {
      "name": "My Theme",
      "description": "A starter storefront.",
      "author": "Your Name",
      "category": "storefront",
      "schema": 2,
      "builder": "full"
    }
    ```

    `schema: 2` enables theme-level blocks and `@theme` targeting. `builder`
    selects the merchant's editing surface; `full` is the default.
  </Step>

  <Step title="Add a layout">
    Pages share this shell. Script and stylesheet URLs come from `platform`
    rather than literal paths.

    ```slurp site/layouts/base.slurp theme={null}
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>${ storefront.name }</title>
        <link rel="stylesheet" href="/css/theme.css" />
        <link rel="stylesheet" href="${ platform.fonts_css }?family=inter:400,700" />
        <script defer src="${ platform.sdk }"></script>
        <script defer src="${ platform.cart }"></script>
        <script defer src="${ platform.alpine }"></script>
      </head>
      <body>
        <slot />
      </body>
    </html>
    ```

    <Warning>
      Do not hardcode those script URLs. They are versioned by the platform, and
      a literal path is frozen at the version it names. See
      [Platform assets](/themes/reference/platform).
    </Warning>
  </Step>

  <Step title="Add an editable section">
    The `section { }` frontmatter becomes a form in the builder.

    ```slurp site/sections/Hero.slurp theme={null}
    ---
    section {
      name: "Hero"
      max_per_page: 1
      settings {
        heading:  text = "Welcome"
        subtitle: text = "Digital goods, delivered instantly."
        accent:   color = "#6366f1"
      }
    }
    ---
    <section style="border-top: 4px solid ${ section.settings.accent }">
      <h1 data-bs-edit="heading">${ section.settings.heading }</h1>
      <p data-bs-edit="subtitle">${ section.settings.subtitle }</p>
    </section>
    ```

    `data-bs-edit` makes an element editable in place. Its value is the settings
    key written back to.
  </Step>

  <Step title="Add the page">
    A page places `{sections}` without naming which sections go there. The
    merchant controls that, starting from the defaults in the next file.

    ```slurp site/pages/index.slurp theme={null}
    {layout "@layouts/base"}
      <main>
        {sections}
      </main>
    {/layout}
    ```

    <Note>
      An element form, `<layout src="@layouts/base">`, also exists. Prefer the
      block form. The element form builds its node with no head slot, so a
      `{head}` block inside it renders in the body, where those tags have no
      effect.
    </Note>
  </Step>

  <Step title="Add default content">
    `templates/index.json` supplies the content a store starts with when the
    theme is installed. Its filename matches the page.

    ```json site/templates/index.json theme={null}
    {
      "sections": [
        {
          "id": "hero",
          "type": "Hero",
          "settings": { "heading": "My store" }
        }
      ]
    }
    ```

    `type` matches `sections/Hero.slurp`. Omitted settings fall back to the
    schema defaults.
  </Step>

  <Step title="Write the stylesheet">
    ```css site/css/theme.css theme={null}
    body { font-family: Inter, system-ui, sans-serif; margin: 0; }
    section { padding: 4rem 1.5rem; }
    h1 { font-size: 2.5rem; margin: 0 0 .5rem; }
    ```

    `base.slurp` links this file, so it must be present in the bundle.
    Publishing rejects a theme whose linked stylesheet is missing. Most themes
    generate it with Tailwind and commit the output.
  </Step>
</Steps>

## Render it

`slurp build` has no store to query, so the platform URLs are supplied
directly:

```json dev-globals.json theme={null}
{
  "platform": {
    "sdk": "http://localhost:5004/_bs/r/2/sdk.js",
    "cart": "http://localhost:5004/_bs/r/2/cart.js",
    "alpine": "http://localhost:5004/_bs/r/2/alpine.js",
    "fonts_css": "http://localhost:5004/_bs/fonts.css"
  },
  "storefront": { "name": "Dev Store", "currency": "USD" }
}
```

```bash theme={null}
slurp build --input site --output dist --globals dev-globals.json
```

<Warning>
  Without `--globals`, every `${ platform.* }` resolves to nothing and the page
  renders `<script src="">`. The page loads, appears close to correct, and has
  no JavaScript at all.
</Warning>

`dist/pages/index.html` is the full document, with `${ storefront.name }` and
every `${ platform.* }` resolved:

```html dist/pages/index.html theme={null}
<!doctype html><html lang=en><meta charset=utf-8><title>Dev Store</title>
<link href=/css/theme.css rel=stylesheet>...<body><main></main>
```

Then serve it:

```bash theme={null}
slurp-dev --source-dir site --theme-dir dist --port 3500 --globals dev-globals.json
```

<Note>
  Use the `slurp-dev` binary, not `slurp dev`. The subcommand forwards only
  `--port` and `--fixtures`, so it cannot pass `--globals`, and the platform
  URLs resolve empty.
</Note>

### `{sections}` in a static build

`<main></main>` above is expected. Section content lives in the merchant's
database and `slurp build` has no store to read, so `{sections}` renders
nothing. `templates/index.json` is applied when a store installs the theme, not
at build time.

To render a section template, pass a `section` object directly. It is an
ordinary context key:

```json preview-globals.json theme={null}
{
  "platform": { "...": "as above" },
  "section": {
    "id": "hero",
    "type": "Hero",
    "settings": { "heading": "My store", "accent": "#6366f1" }
  }
}
```

```bash theme={null}
slurp build --input site --output dist --globals preview-globals.json
```

```html dist/sections/Hero.html theme={null}
<section style="border-top: 4px solid #6366f1"><h1 data-bs-edit=heading>My store</h1>...
```

<Warning>
  This path does not merge. The template sees exactly what is written, so
  defaults are not filled in, numbers are not clamped and `richtext` is not
  sanitized. Use it to check markup, not to verify schema behaviour.
</Warning>

`slurp build` writes an HTML file for every `.slurp` outside `components/` and
`layouts/`, which accounts for `dist/sections/Hero.html`. Those are local build
output and are not part of the published bundle.

## Deploy to a store

Themes deploy from GitHub. There is no upload.

<Steps>
  <Step title="Push the repository">
    Commit everything, including `site/css/theme.css`.
  </Step>

  <Step title="Connect it">
    In the dashboard, open **My Store**, connect the GitHub repository and
    select the branch. ByteSell reads the tree, locates the directory containing
    `theme.json` and validates it before accepting the connection.
  </Step>

  <Step title="Push again">
    Every push to that branch redeploys. Check the deploy status, then set the
    theme live.
  </Step>
</Steps>

Two connection failures are common, and both indicate the wrong directory:
`no theme.json manifest at the theme root` and `theme.json found, but no .slurp
files in this folder - is it the right one?`.

## Next

<CardGroup cols={2}>
  <Card title="Pages and routing" icon="signs-post" href="/themes/pages">
    Dynamic routes and special pages.
  </Card>

  <Card title="Sections and blocks" icon="table-cells" href="/themes/sections">
    Nested blocks, zones and default content.
  </Card>

  <Card title="Store data" icon="database" href="/themes/data">
    The `storefront` object and fetching products.
  </Card>

  <Card title="Publishing" icon="upload" href="/themes/publishing">
    Versioning, the schema gate, and every rejection.
  </Card>
</CardGroup>
