# create-brainerce-store

Scaffold a production-ready e-commerce storefront connected to [Brainerce](https://brainerce.com) — cart, checkout, variants, coupons, auth, SEO, and i18n wired out of the box.

```bash
npm create brainerce-store@latest my-store -- --connection-id vc_xxxxxxxx
# or
pnpm create brainerce-store my-store --connection-id vc_xxxxxxxx
```

Run it with no flags for a fully interactive setup. The CLI fetches your store's name, currency, language, and locales from the connection ID (`vc_*`, from your Brainerce dashboard), so the generated store matches the real channel from the first `dev` run.

## The design

Every scaffold ships **Atelier** — a complete, AI-built storefront look (not just a color theme): warm editorial gallery with soft washes + glass surfaces, a floating hero collage, near-full-bleed product grid, styled popover dropdowns, a mini-cart drawer that opens on add-to-cart, and an RTL-safe fly-to-cart micro-interaction. Fully de-branded — driven by your store's name, catalog and dashboard content.

It's a starting point, not a lock-in: the entire look lives in `src/ui/` + `globals.css` and is designed to be rewritten (see below). The shipped texts are **vertical-neutral placeholder content** (like any template's sample copy: they name no product category) — your catalog replaces the imagery automatically, and the copy (hero, story, footer tagline) lives in `messages/` ready to be rewritten in your own voice by you or an AI session. On a brand-new store with no products yet, the homepage hero shows a designed placeholder that swaps for your first published products.

## Blank-canvas mode

```bash
npm create brainerce-store@latest my-store -- --connection-id vc_xxx --canvas
```

`--canvas` ships `src/ui/` as bare, semantic, essentially-unstyled skeletons (`DESIGN ME` markers included) with zero aesthetic opinion — commerce stays fully wired. It's the starting point for designing a storefront from scratch with an AI session, and the authoring substrate for new gallery designs. Canvas mode skips the design pack entirely.

## AI-first by default

Every scaffolded store is ready to be redesigned by an AI coding session:

- **`CLAUDE.md`** — auto-loaded by Claude Code; teaches the session the one rule (`core/` is the platform's, `ui/` is yours) before it touches anything.
- **`AGENTS.md`** — the same context for other agentic tools.
- **`/design <your art-direction brief>`** — a ready-made slash command that walks the full redesign: concept → implementation in `ui/` → verification (tsc, real browser, screenshots, RTL checks).
- **`AI-GUIDE.md`** — the design contract: file map, per-page hook contracts, verification loop, and hard-won RTL/i18n gotchas from real agency builds.

## Architecture (core/ui)

- `src/core/` — platform-owned commerce: client, auth, providers, and data/behavior hooks that return state + handlers, never JSX. Don't modify.
- `src/ui/` — 100% replaceable presentation. Delete-and-rebuild is encouraged; the store keeps working.
- `src/app/` — thin routes composing the two (~10 lines each).
- An ESLint boundary rule enforces the split in both directions.

Full details: [TEMPLATE-ARCHITECTURE.md](./TEMPLATE-ARCHITECTURE.md).

## Flags

| Flag                   | Description                                            | Default            |
| ---------------------- | ------------------------------------------------------ | ------------------ |
| `--connection-id <id>` | Brainerce vibe-coded connection ID (`vc_*`)            | prompted           |
| `--defer-connection`   | Scaffold now, connect later with `npm run connect`     | off                |
| `--canvas`             | Bare unstyled `src/ui/` skeletons for AI-driven design | off                |
| `--language <lang>`    | Store language (`en`, `he`). **One-way** — see below   | fetched from store |
| `--pkg-manager <pm>`   | `npm`, `pnpm`, `yarn`, `bun`                           | auto-detected      |
| `--framework <fw>`     | `nextjs` (Vite/Remix coming)                           | `nextjs`           |
| `--api-url <url>`      | Brainerce API base URL (or `BRAINERCE_API_URL` env)    | auto-discovered    |
| `--no-git`             | Skip git initialization                                | git on             |
| `--no-install`         | Skip dependency installation                           | install on         |

Pass `.` as the project name to scaffold into the current directory.

`--language` is the one decision that cannot be changed after scaffolding: it
picks which `messages/` ship and the `<html lang>` / `dir` of every page.
`npm run connect` and `npm run setup` refresh the store name and currency from
the live channel, never the language — a store in the wrong language is
re-scaffolded, not adjusted. Pass it explicitly when you know it (for example
`--language he` for a Hebrew merchant); without a channel to read, a deferred
scaffold assumes `en`.

## Building first, connecting later

```bash
npm create brainerce-store@latest my-store -- --defer-connection --language he
cd my-store
npm run connect      # one browser approval; creates a store + channel if needed
npm run build        # NEXT_PUBLIC_* values are baked at build time
```

`--defer-connection` writes a placeholder channel id and skips the approval,
so an AI builder can construct the whole storefront without stopping. The
scaffold then knows no store: the name it bakes is the project directory name
and the currency is `USD`. `npm run connect` writes the real channel id and
runs `npm run setup`, which fetches the real name and currency into
`.env.local`. At runtime the storefront prefers the live store name and
currency from the API (server components, `<title>`, JSON-LD, the Open Graph
card) and falls back to those `.env.local` values, then to the scaffold
literal, so a connected store is branded correctly on the first request
without a rebuild. The `NEXT_PUBLIC_*` fallbacks the client bundle carries are
inlined at build time, though, so **rebuild before deploying and restart a
running dev server** after connecting — `connect` says so when it finishes.

`npm run connect -- --seed-products '[{"name":"Burr Grinder","basePrice":389}]'`
seeds a starter catalog in the same approval and reports, per product, whether
it was created and whether it is published to this channel; a product that
exists but is not published is named so you can publish it from the dashboard
rather than add it twice. On PowerShell put the JSON in
`BRAINERCE_SEED_PRODUCTS` instead of the flag.

## Reading the connection

Before scaffolding, the CLI reads the channel from `/api/vc/<id>/info` so the
generated project gets the real store name, currency and language rather than
guesses. It walks production first, then staging, and stops at the first
environment that answers. When it has to fall back, it says so and names the
URL the project will be wired to.

That endpoint checks the request's `Origin` against the channel's **Domain**
and **Allowed Origins**, and the match counts the **port**. A Test channel with
an empty Domain box accepts anything; one with `localhost:3000` recorded will
refuse a bare `http://localhost`. The CLI therefore presents
`http://localhost:3000` first and plain `http://localhost` second, and reports
what every environment said rather than only the last one. A `403` from
production must never surface as "not found on staging".

A channel it cannot read is a hard stop, not a warning. Build-time
`NEXT_PUBLIC_*` values are inlined into the client bundle and cannot be
corrected at deploy time, so guessing `USD` / `en` here would ship a storefront
quoting the wrong currency.

## Requirements

Node `^20.19.0 || ^22.13.0 || >=24.0.0`.

## After scaffolding

```bash
cd my-store
pnpm dev          # store at http://localhost:3000
```

Want a unique look? Open the folder in Claude Code and run `/design <your art-direction brief>`.
