# Shop

> [Depends: ecommerce](/docs/enable/ecommerce)

A product listing at `/shop` and a page per product, for the cart [`vela enable ecommerce`](/docs/enable/ecommerce) added. The pages are written in your payments provider's own terms, and they are yours: the generator never writes over a file that exists.

### Syntax

```
$ vela generate shop
```

### Options

- `--provider <provider>` - Optional. The shop follows the project's [payments](/docs/enable/payments) provider, so this only confirms it; a different provider is refused.

Every product page has an `<AddToCart>` button. If any of the files below already exists, nothing is written and the command names the file: run [`vela destroy shop`](/docs/destroy/shop) to remove a shop generated before, or move the file aside.

### Stripe

> [Depends: backend](/docs/enable/backend)

The pages read the catalog the payments sync copies from Stripe into PocketBase (`stripe_products` and `stripe_prices`), on the server:

```
src/routes/(public)/shop/+page.server.ts
src/routes/(public)/shop/+page.svelte
src/routes/(public)/shop/[product]/+page.server.ts
src/routes/(public)/shop/[product]/+page.svelte
```

The listing shows every active product with its default one-time price, and the product page its description, first image and every active one-time price, with a picker when there is more than one (sizes, say; name them with the price's nickname in the dashboard). A product's URL is its id, or `metadata.slug` when you set one on the product in the Stripe dashboard. Products, prices, images and descriptions are edited in Stripe; the sync runs every ten minutes.

### Shopify

The pages query the Storefront API:

```
src/routes/(public)/shop/+page.ts
src/routes/(public)/shop/+page.svelte
src/routes/(public)/shop/[handle]/+page.ts
src/routes/(public)/shop/[handle]/+page.svelte
```

The loads are universal (the Storefront token is public) and not prerendered, so the catalog changes without a rebuild and a static site renders the pages behind its fallback. The product page offers each option (size, colour) as a picker and resolves the variant to add; a variant that is sold out says so. Products live in Shopify admin and must be published to the Headless channel the token belongs to.

### WhatsApp

WhatsApp has no catalog of its own, so the products are a module you edit:

```
src/lib/catalog.ts
src/routes/(public)/shop/+page.svelte
src/routes/(public)/shop/[id]/+page.ts
src/routes/(public)/shop/[id]/+page.svelte
```

`catalog.ts` lists each product's `id`, `name`, `description`, `price` (in `site.currency`, written as you would write it: `4.5`) and `image`. Leave the price out for an item the business quotes in the chat. The product pages list their entries from the module, so a static site prerenders every one of them.

With the [CMS](/docs/enable/cms) enabled, the catalog is content instead of a module: a `CmsCollection` named `catalog` in the root layout scope, which the listing and the product pages both read, so products are added and priced in place with `?edit`. Prices are still in `site.currency`.

### What it is not

A shop is pages over a catalog that lives elsewhere (Stripe, Shopify, your module or the CMS). Stock, categories and search are not generated; on Shopify the listing shows the first hundred products.