# AGENTS.md — Bakery storefront template

If you are an AI agent (Claude, Cursor, Aider, devin, …) working on this storefront, **start here.**

## TL;DR for rebranding

To rebrand this storefront end-to-end as a different merchant:

1. **Edit `lib/brand.ts`.** Every visible string reads from this file.
2. **Edit `app/globals.css`** — the `@theme { … }` block holds the design tokens (palette, radius, font references).
3. **Edit `.env.local`** — set `NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY` (optional: `NEXT_PUBLIC_SITE_URL`).

That is the entire rebrand. Do not modify any `.tsx` file in `app/` or `components/` for content changes — they are design-only and read from `brand`.

## Rules

- ✅ All content edits → `lib/brand.ts`
- ✅ All design-token edits → `app/globals.css` `@theme` block
- ✅ Pages use **ISR**: `export const revalidate = <seconds>` + SDK reads with `cacheOptions: { revalidate, tags }`
- ✅ Client islands (header active link, cart pill, product modal) live behind `<Suspense>`
- ❌ Don't hardcode strings. If a string isn't in `brand`, add a new field to the `Brand` interface.
- ❌ Don't enable `cacheComponents: true` in `next.config.ts`. We deploy on Cloudflare Workers; `'use cache'` postponed state blows past CF's 128MB zlib limit.
- ❌ Don't add `'use cache'`, `cacheTag`, or `cacheLife` anywhere. Use SDK `cacheOptions` instead.
- ❌ Don't use `unstable_cache` — gone in Next 16.

## Page surface

```
app/
  page.tsx                       Home — hero, collection strips, category grid
  shop/page.tsx                  Full catalogue (SDK <CataloguePage/>)
  search/page.tsx                Search (SDK <SearchPage/>)
  collections/[slug]/page.tsx    Collection landing
  categories/[slug]/page.tsx     Category landing

  cart/page.tsx                  SDK <CartPage/>
  checkout/page.tsx              SDK <CheckoutPage/>
  orders/[id]/page.tsx           Post-checkout confirmation (also target of /track-order)

  account/page.tsx               <AccountDashboardPage /> (native, Server Component)
  account/orders/page.tsx        <AccountOrdersPage /> (native)
  account/addresses/page.tsx     Native list + Server Actions for CRUD
  account/wallets/page.tsx       Native list + Server Actions for CRUD
  login/page.tsx                 redirect → /account (iframe owns sign-in UI)
  signup/page.tsx                redirect → /account (iframe owns sign-up UI)

  contact/page.tsx               Contact form (Server Action wiring TODO; currently fakes submit)
  track-order/page.tsx           Guest order lookup → /orders/[id]

  about/page.tsx                 Brand story
  faq/page.tsx                   FAQ
  shipping/page.tsx              Standalone shipping policy
  returns/page.tsx               Standalone returns policy
  accessibility/page.tsx         Accessibility statement (WCAG 2.1 AA)
  terms/page.tsx                 Terms of Service
  privacy/page.tsx               Privacy Policy

  sitemap-page/page.tsx          Human-readable HTML sitemap
  sitemap.ts                     XML sitemap (search engines)
  robots.ts                      robots.txt
  llms.txt/route.ts              LLM-friendly Markdown index
  opensearch.xml/route.ts        Browser address-bar search description
  error.tsx, not-found.tsx       Global boundaries
```

## File ↔ brand-field map

| File | Reads from `brand` |
|---|---|
| `app/layout.tsx` | identity, contact, socials, schemaType (Organization JSON-LD), `metadataBase` |
| `app/page.tsx` | `brand.hero` (Hero badge / title / subtitle) |
| `app/about/page.tsx` | `brand.about` |
| `app/faq/page.tsx` | `brand.faq` |
| `app/terms/page.tsx` | `brand.terms` |
| `app/privacy/page.tsx` | `brand.privacy` |
| `app/shipping/page.tsx` | `brand.shipping` |
| `app/returns/page.tsx` | `brand.returns` |
| `app/accessibility/page.tsx` | `brand.accessibility` |
| `app/contact/page.tsx` | `brand.contactPage`, `brand.contact` |
| `app/track-order/page.tsx` | `brand.trackOrder` |
| `app/account/*/page.tsx` | `brand.account` (eyebrows + titles only — Cimplify Link iframe owns the UI) |
| `app/login/page.tsx`, `app/signup/page.tsx` | `brand.account` (metadata only — both redirect to `/account`) |
| `app/llms.txt/route.ts` | `brand.llms`, contact, currency |
| `app/opensearch.xml/route.ts` | `brand.shortName`, `brand.name` |
| `app/sitemap.ts`, `robots.ts` | derives URLs from product/category data |
| `app/not-found.tsx` | `brand.name` (page title) |
| `components/header.tsx` | `brand.shortName`, `brand.microTag`, `brand.header.nav` |
| `components/footer.tsx` | `brand.footer`, `brand.contact`, `brand.socials` |

## Bakery-specific notes

- Product detail uses a **URL-driven modal** (`?product=<slug>`), not a static `/products/[slug]` route. Fits impulse-purchase food UX.
- Schema.org `@type` is `Bakery` — set in `brand.schemaType`.
- Mock seed: `--seed default`. To preview a different industry, edit `dev:mock` in `package.json`.

## Known TODOs (not blocking, but worth knowing)

- `app/contact/contact-form.tsx` fakes a successful submit. In production, wire a Server Action that calls `client.support.sendMessage(...)` from `@cimplify/sdk/server`.
- `components/newsletter.tsx` (homepage strip) similarly fakes submit. Wire to a real list provider.
- Hero / lookbook imagery is Unsplash placeholder — replace with merchant assets.

## Customizing SDK components

For anything beyond `lib/brand.ts` + `app/globals.css`, lean on the SDK's prebuilt components rather than reinvent. **Especially for product customization** (variants, add-ons, bundles, composites, services with scheduling) — the SDK already gets price math, axis matching, and cart payload contracts right. Default to ejecting and restyling:

```bash
cimplify add cart-drawer
cimplify add variant-selector
cimplify add product-page
```

Then edit the local copy. **Don't change the cart payload shape** unless you're also touching the SDK mock + backend lens. Full ejection rules and the customizer contract are in the SDK-level [`AGENTS.md`](../../AGENTS.md) → "Don't reinvent product customization".

## Quick start

```bash
bun install
bun dev                 # boots mock + Next dev server
```

Open <http://localhost:3000>.
