---
name: storefront
description: Scaffolds, white-labels, generates a logo for, and deploys the customer-facing eSIM storefront, then verifies it actually serves and repairs it once if not. Use when the operator asks to create, rebrand, or deploy their storefront, shop, or customer-facing site.
argument-hint: "[create|logo|deploy|targets|clerk|rebrand] [dir]"
---

# Storefront

Roll out the customer-facing eSIM storefront (white-labeled) on top of your Carrier fleet.

Works for **any developer** with Carrier MCP (`https://mcp.carrier.llc/mcp`) or the `carrier` CLI. You do not need an image-API key on your laptop.

- **create** → `carrier site create <dir>`  
  Captures brand name, domain, accent, support email. Writes `src/brand.config.ts` **and** `public/brand/logo.svg` (unique mark from the brand name + accent).
- **logo** → `carrier site logo <dir>` or MCP tool `generate_storefront_logo`  
  Regenerates the mark. SVG always. PNG is added only when Carrier (or this box) has an OpenAI image key — optional, never required.
- **rebrand** → edit `src/brand.config.ts`, then `carrier site logo <dir>` and rebuild.
- **targets** → `carrier site targets <dir>`  
  Shows which hosts are installed, logged in, and ready: Cloudflare, Vercel, Netlify, Fly. Names the one a deploy would pick.
- **deploy** → `carrier site deploy <dir>`  
  Picks a host automatically: one the project is already configured for, else Cloudflare (what the template is built for). Force with `--target cloudflare|vercel|netlify|fly`. Builds with the right script per host (`cf:build` for Cloudflare, `build` elsewhere), **stages runtime secrets before the code**, deploys, then **verifies the site actually serves** and repairs it once if it does not.  
  Flags: `--no-secrets`, `--no-verify`, `--clerk`, `--domain`, `--autofix-agent`.
- **clerk** → `carrier site clerk <dir>`  
  Four tiers, best first: create via Platform API (`CLERK_PLATFORM_API_KEY`) → mint a **keyless** app with the Clerk CLI, no account needed → reuse keys already on the machine → print the dashboard steps. Writes keys to `.env.local` and sets allowed origins + redirect URLs. `--no-create` reuses only; `--production` pulls prod keys.

Secrets are staged **before** the deploy, not after. On Cloudflare they ride along in the same version via `--secrets-file`, so there is never a moment where the new code is live without them — that gap is what made a green deploy serve 500s.

After deploying, `/`, `/shop` and `/help` are probed. A failure is classified, not guessed at:

| Symptom | Cause | What happens |
|---|---|---|
| `/` + `/shop` 500, `/help` 200 | `CARRIER_API_KEY` absent | re-stage, redeploy |
| public pages fine, auth routes 5xx | Clerk keys absent | provision, rebuild, redeploy |
| `/shop` 200 but no plans | catalog empty upstream | reported, not retried |
| nothing reachable | deploy did not land | reported |

One repair attempt, then re-probe. Still broken on Cloudflare → rolled back to the previous version and a non-zero exit. Never loops.

MCP (any authenticated Carrier user):

```
generate_storefront_logo
  name: Bananas
  accent: #FF8A00
  tagline: Data that works wherever you land.
```

Write the returned `svg` to `public/brand/logo.svg`. Nav and icons read that path.

MCP over stdio (these drive host CLIs on your machine, so they are local-only):

```
list_deploy_targets        dir: ./storefront
deploy_storefront          dir: ./storefront   [target, name, skip_build, push_secrets, verify, domain]
provision_storefront_clerk dir: ./storefront   [name, production, no_create, url]
```

`deploy_storefront` returns `verified`, `diagnosis`, `probes` and `repair_hint`, so a caller can tell a working deployment from one that merely finished.

Wire-up. Every key the template reads is declared in `TEMPLATE_ENV_KEYS`
(`src/cli/lib/storefront-secrets.ts`) and a test fails the build if the template
gains one that is not:

| Key | Delivery | Missing means |
|---|---|---|
| `NEXT_PUBLIC_CARRIER_API_URL` | build-time | falls back to mock plans |
| `NEXT_PUBLIC_APP_URL` | build-time | guest checkout builds broken URLs |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | build-time | auth routes fail |
| `CARRIER_API_KEY` | runtime secret | **`/` and `/shop` return 500** |
| `CLERK_SECRET_KEY` | runtime secret | auth routes fail |
| `STRIPE_SECRET_KEY` | runtime secret | guest checkout fails at request time |

`NEXT_PUBLIC_*` values are inlined by Next at build time, so they must be in
`.env.local` *before* the build — pushing one as a runtime secret looks like it
worked and changes nothing.

Also: plans come from `list_package_templates` / `pricing_plans`, and
`credential_status` is worth confirming before going live.

Creating a Clerk application through the Platform API needs a partner token and
is not self-serve. The CLI's keyless mode covers that gap — it mints a claimable
app with no account. Claim it at dashboard.clerk.com to keep it, and use
`--production` for real production keys.
