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

# Platform assets

> Platform-served runtime assets.

Alpine, the icon set, the ByteSell SDK, the cart store and web fonts are served
and versioned by the platform. A theme references them through `platform`, never
by a literal path.

```slurp theme={"languages":{"custom":["/languages/slurp.json"]}}
<link rel="stylesheet" href="${ platform.fonts_css }?family=inter:400,700" />
<script defer src="${ platform.lucide }"></script>
<script defer src="${ platform.alpine_collapse }"></script>
<script defer src="${ platform.sdk }"></script>
<script defer src="${ platform.cart }"></script>
<script defer src="${ platform.alpine }"></script>
```

## The object

| Expression                 | Value                        |
| -------------------------- | ---------------------------- |
| `platform.runtime_version` | The current runtime version  |
| `platform.base`            | `{origin}/_bs/r/{version}`   |
| `platform.alpine`          | Alpine core                  |
| `platform.alpine_collapse` | The Alpine collapse plugin   |
| `platform.lucide`          | The icon runtime             |
| `platform.sdk`             | `ByteSellSDK`                |
| `platform.cart`            | The shared Alpine cart store |
| `platform.icon_base`       | `{origin}/_bs/icon`          |
| `platform.fonts_css`       | `{origin}/_bs/fonts.css`     |

<Warning>
  Load order is the theme's responsibility. The collapse plugin must register
  before Alpine core starts, so Alpine loads last. The shipped order is
  collapse, sdk, cart, alpine.
</Warning>

Icons and fonts are not runtime-versioned. Icon content is pinned by the
vendored icon set, so versioning \~1,900 files on every SDK change would
invalidate them all without cause.

## Symbolic references

These assets are served `immutable` with a one-year cache, so the URL is the
only delivery mechanism. Incrementing the runtime version moves every store onto
the new bytes on its next render, with no theme republish.

A hardcoded path has three consequences:

* Security fixes do not reach the theme. An immutable URL is never revalidated.
* The next version increment produces a 404. An unknown version is rejected
  rather than served current bytes under an old URL.
* Theme-local names do not resolve. `/js/vendor/alpine.min.js` requires shipping
  the bytes in the bundle, which counts against the merchant's storage and
  forks the SDK.

## Fonts

`GET /_bs/fonts.css?family=inter:400,700` returns `@font-face` rules pointing at
the store's own origin. The bytes are fetched from upstream once, ever, and
cached.

<Warning>
  Do not link a font CDN from a theme. Doing so sends the buyer's IP address to
  a third party, which the merchant cannot consent to on the buyer's behalf.
</Warning>

The family list is an allowlist. It admits only OFL and Apache licensed
families, and restricts the endpoint to those families rather than allowing
arbitrary upstream fetches. An unlisted family is ignored rather than fetched,
and an unlisted weight is ignored rather than approximated.

## Icons

One request per icon, from `${ platform.icon_base }/{name}.svg`. Icons are
served individually because a theme cannot know at build time which icons a
merchant will select through an `icon` setting.

Names are kebab-case.

## Local development

`slurp build` has no platform to query, so supply the same object with
`--globals`:

```json dev-globals.json theme={"languages":{"custom":["/languages/slurp.json"]}}
{
  "platform": {
    "alpine": "http://localhost:5004/_bs/r/2/alpine.js",
    "sdk": "http://localhost:5004/_bs/r/2/sdk.js",
    "cart": "http://localhost:5004/_bs/r/2/cart.js",
    "fonts_css": "http://localhost:5004/_bs/fonts.css"
  }
}
```

<Warning>
  Without it, every `${ platform.* }` renders empty. The page loads, appears
  close to correct, and has no JavaScript at all. Keep the version in those URLs
  current, or local pages request a version the server rejects.
</Warning>
