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

# Vite Design

> Design a Join Markt storefront with React, Tailwind, and the Visual Builder.

# Vite Design

**Vite only** — React + Tailwind + TypeScript.

For Nunjucks (`.njk`), open [Nunjucks Design](/storefront/nunjucks-design).

***

## What you design

| Layer           | Where                                        |
| --------------- | -------------------------------------------- |
| Layout shell    | `App.tsx` — navbar, footer, routes           |
| Pages           | `src/pages/*.tsx` — one file per route       |
| UI blocks       | `src/components/` (flat; `ui/` ok)           |
| Colors / tokens | `src/theme/colors.css` only                  |
| Global CSS      | `src/index.css` — Tailwind + layout          |
| Catalog data    | `src/lib/storefront-api.ts` and `useStore()` |

Starter: `templates/markt-vite-storefront/`

***

## Scaffold

```bash theme={null}
cp -r templates/markt-vite-storefront templates/my-theme
cd templates/my-theme
npm install
npm run dev
```

Sellers use [Theme Builder](/guides/theme-builder) on the same Vite theme.

***

## Required routes

| Path             | Page file          |
| ---------------- | ------------------ |
| `/`              | `LandingPage.tsx`  |
| `/products`      | `ProductsPage.tsx` |
| `/product/:slug` | `ProductPage.tsx`  |
| `/privacy`       | `PrivacyPage.tsx`  |
| `/terms`         | `TermsPage.tsx`    |
| `/refunds`       | `RefundsPage.tsx`  |

Register in `App.tsx` with React Router.

***

## Design rules

1. Colors only in `theme/colors.css`
2. Landing sections stay inside `LandingPage.tsx`
3. Keep `lib/` to the four platform files
4. On-hold: `isStoreProductOnHold(product)` — disable cart / buy
5. Respect product **groups** on grids
6. Policies via `LegalPolicyPage` — see [Policy Pages](/storefront/policy-pages)
7. Checkout is platform-only — no payment form in the theme

Footer links use Vite paths: `/privacy`, `/terms`, `/refunds`.

***

## Policy page example

```tsx theme={null}
import { LegalPolicyPage } from '@/components/legal-policy-page'

export const PrivacyPage = () => (
  <LegalPolicyPage
    title="Privacy Policy"
    policyKey="privacyPolicy"
    emptyMessage="No privacy policy has been added yet."
  />
)
```

***

## Publish checklist

* `npm run build` passes
* Preview iframe shows required routes
* Empty / loading states for catalog and policies
* On-hold items not purchasable

***

## Next

* [Vite Storefront](/storefront/vite)
* [Template Structure](/storefront/template-structure)
* [Build a Custom Theme](/storefront/custom-themes)
