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

# Build a Vite theme

> Build a Join Markt theme with plain TypeScript sections, no framework.

A Vite theme is plain TypeScript, no framework. Each section exports `mount` and `update`. Good for canvas, animation and fast pages.

> [!NOTE]
>
> Real example: **Orbit** in `templates/themes/orbit/`.

## The folder

The same as React. Only the section file changes: `index.ts` instead of `index.tsx`.

```text theme={null}
my-theme/
├── theme.json              # "runtime": "vite"
├── index.html
├── config/  groups/  templates/  public/
└── src/
    ├── theme.css           # your styles
    ├── lib/                # your own helpers
    └── sections/
        └── spacer/
            ├── index.ts    # exports mount + update
            └── schema.json
```

## Steps

**1. Write theme.json**

```json theme.json theme={null}
{
  "engine": "join-markt/v2",
  "id": "my-theme",
  "name": "My Theme",
  "version": "1.0.0",
  "runtime": "vite"
}
```

**2. Write index.html**

The same file as in React. It must load `/src/platform/entry.tsx`.

**3. Add a section**

`schema.json` is the same as in React. The design:

```ts src/sections/spacer/index.ts theme={null}
import type { RuntimeContext } from '@/platform'

export function mount(el: HTMLElement, ctx: RuntimeContext) {
  update(el, ctx)
}

export function update(el: HTMLElement, ctx: RuntimeContext) {
  const settings = ctx.section.settings ?? {}
  const height = Number(settings.height ?? 48)
  const mobile = Number(settings.mobile_height ?? 32)
  el.innerHTML = ''
  const box = document.createElement('div')
  box.setAttribute('aria-hidden', 'true')
  box.style.setProperty('--space', `${height}px`)
  box.style.setProperty('--space-m', `${mobile}px`)
  box.className = 'spacer'
  el.appendChild(box)
}
```

| Function | When it runs |
| - | - |
| `mount` | once, when the section appears |
| `update` | every time the seller changes a setting |

**4. Put it on the home page**

`templates/index.json` is the same as in React.

**5. Zip, upload, publish**

See [Upload rules](https://docs.joinmarkt.com/themes/upload-rules.md).

> [!TIP]
>
> Orbit keeps small helpers in `src/lib/` (`dom.ts`, `section.ts`, `store.ts`, `cart.ts`, `motion.ts`). You can copy them. They are theme files, not platform files.

## What `ctx` holds

| Field | What it is |
| - | - |
| `ctx.section.settings` | the section's settings |
| `ctx.section.blocks` | its blocks, in order |
| `ctx.products` | the store's public products |
| `ctx.cart` | the cart |
| `ctx.shop` | store name, logo, links |

## Styles

Put your CSS in `src/theme.css`. Tailwind works too, with `tailwind.config.ts`. Use the theme colors as CSS variables, like `var(--jm-color-primary)`, so the seller's color settings apply.

## Cart and checkout

No API calls needed. Add `data-jm-*` attributes to your HTML, or call `window.JoinMarkt`:

```ts theme={null}
const added = window.JoinMarkt?.cart.add(product.id, { quantity: 1 })
document.addEventListener('jm:cart', () => {
  badge.textContent = String(window.JoinMarkt?.cart.count ?? 0)
})
```

| `window.JoinMarkt` | What it does |
| - | - |
| `cart.add(idOrSlug, { variant, quantity })` | add to cart |
| `cart.items`, `cart.count`, `cart.total` | read the cart |
| `cart.remove(lineId)`, `cart.setQuantity(lineId, n)` | change the cart |
| `cart.applyCoupon(code)`, `cart.removeCoupon()` | coupons |
| `cart.checkout()` | go to checkout |
| `formatPrice(amount)` | price in the buyer's currency |
| `navigate(path)` | go to another page |

Events on `document`: `jm:cart` and `jm:checkout-error`. Attribute list: [Commerce attributes](https://docs.joinmarkt.com/themes/commerce-attributes.md).

## Next

> [card] [Upload rules](https://docs.joinmarkt.com/themes/upload-rules.md)
>
> What gets kept, and every error.

> [card] [Runtimes](https://docs.joinmarkt.com/themes/runtimes.md)
>
> The same section in all three.


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