# AGENTS.md — operating guide for AI coding agents

This file is for Claude Code, Codex, Cursor, OpenClaw, GitHub agents, and any
other AI agent working in this repository — including the agent that built and
operates the live store. Humans should read README.md first; this file is the
machine-oriented version.

## What this project is

Pagemage is a self-hosted storefront starter: a static sales site + five
serverless functions that sell a digital product (the starter itself) through
Stripe Hosted Checkout, with payment-verified instant delivery. It deploys to
Vercel by pushing to `main`. Live store: https://www.pagemage.tech

The product's design goal: an agent should be able to turn this into a
customer's storefront — rebrand, rewrite copy, change the offer — safely,
without breaking the money path.

## Architecture (everything is small and intentional)

```
index.html                  sales page (the product demo IS the product)
guide.html                  public setup guide (SEO + pre-sale trust)
how-it-works.html           technical deep-dive (store-side marketing)
sell-online.html            field guide (store-side marketing)
terms/privacy/refunds.html  legal pages (store voice — buyers rewrite these)
404.html                    branded not-found
success.html + success.js   post-purchase: verifies session, unlocks download
styles.css                  ALL styling; design tokens at the top, six themes
                            via [data-theme] blocks (paper/midnight/plum/
                            sand/slate/forest)
script.js                   palette system + persistence, pricing cards
                            (rendered from /api/products), checkout calls,
                            discount-list form, abandoned-checkout recovery,
                            changelog strip, analytics events
fonts.css + fonts/          self-hosted fonts (zero third-party requests)
sections/                   paste-in section templates for buyers
api/*.js                    Vercel functions (see below)
scripts/                    build/test tooling (not shipped to buyers)
api/assets/                 the product archive + VERSION stamp (never served
                            statically — api/ is not a static path)
```

## API contract (do not break)

| Endpoint | Contract |
| --- | --- |
| `POST /api/create-checkout-session` | body `{tier, ref}` → `{url}` (Stripe Hosted Checkout). `tier` maps through `TIER_PRICE_VARS`. Retries without promotion codes if the key lacks permission. |
| `GET /api/products` | `{tiers:[{tier,name,blurb,recommended,amount,currency,recurring,interval}], configured}` — the page renders cards from this. Cached 5 min per instance. |
| `GET /api/verify-session?session_id=` | `{paid, email, tier, amountTotal, currency}` |
| `GET /api/download?session_id=` | streams `api/assets/pagemage-starter.zip` only after re-verifying payment. Filename is version-stamped. |
| `GET /api/subscribe` | `{enabled}` — discount list is opt-in via `LEADS_GITHUB_TOKEN` |
| `POST /api/subscribe` | `{email, website(honeypot)}` → `{ok}` — appends to `api/leads/leads.json` via GitHub Contents API (merge-on-conflict) |
| `GET /api/dfy-intake` | `{enabled}` — done-for-you brief storage is opt-in via `LEADS_GITHUB_TOKEN` |
| `POST /api/dfy-intake` | `{name, email, package, timeline, …, website(honeypot)}` → `{ok}` — appends to `api/leads/dfy-briefs.json` via GitHub Contents API (merge-on-conflict); also accepts form-encoded no-JS posts and answers with a PRG redirect |
| `GET /api/setup-status` | boolean diagnostics for the store owner — never expose secrets |

## Non-negotiable invariants

1. **CSP is `script-src 'self'`**: no inline `<script>` blocks (JSON-LD data
   blocks are fine — verified), no `onclick=` handlers, no inline `style=`
   attributes. Use external files and CSS classes.
2. **The money path is server-verified twice**: `verify-session` on the page,
   re-verified in `download`. Never trust the client.
3. **`api/` is never served statically** — that's why secrets-adjacent assets
   (the product zip, leads.json) live there.
4. **Design tokens**: every color routes through the `:root` / `[data-theme]`
   blocks in styles.css. Never hardcode colors; new palettes are new token
   blocks.
5. **All animation respects `prefers-reduced-motion`; content works with JS
   disabled** (scripting:none fallback, static fallbacks in HTML).
6. **Zero third-party requests** while browsing — this is a stated selling
   point. Fonts are self-hosted; analytics is same-origin Vercel insights.

## Change workflow (always in this order)

```bash
# edit files...
npm run check          # syntax + validate.mjs: links, anchors, ids, CSP,
                       # labels, heading order, mojibake, JSON, fonts,
                       # FAQ/JSON-LD sync, buyer-archive link invariant
npm run smoke          # API failure-path tests (no keys needed)
npm run build-product  # rebuild api/assets/pagemage-starter.zip IF any
                       # shipped file changed (see INCLUDE in make-zip.mjs);
                       # also bumps sitemap lastmod dates
git commit && git push # push to main = Vercel production deploy
```

If `check` fails, fix before shipping — it has caught real CSP violations,
broken links, stale JSON-LD, and encoding corruption.

## Customization map (what agents are usually asked to do)

| Task | Where |
| --- | --- |
| Rebrand / rewrite copy | `index.html` (plain HTML, tokens above) |
| Change colors / theme | token blocks at top of `styles.css`; pick via `<html data-theme="midnight">` |
| Change price / tiers | Stripe prices + `STRIPE_PRICE_ID*` env vars; card copy in `TIER_FEATURES` (script.js); tier→env map in `TIER_PRICE_VARS` (api/create-checkout-session.js) |
| Add a section | copy a template from `sections/` (they use existing classes) |
| Legal pages | terms/privacy/refunds.html — rewrite for the business |
| Support email | grep `hello@pagemage.tech` (appears in ~10 places) |
| Deploy | push to main (Vercel) or `npx vercel --prod` |

## Sample agent prompt that works with this repo

> Turn this Pagemage storefront into a landing page for [business]:
> keep the Stripe checkout and verified-delivery flow, replace all
> Pagemage-specific copy and the done-for-you section, retheme using the
> token blocks, update legal pages with the business name, run
> `npm run check && npm run smoke`, then deploy.

## Known edges

- `/api/*` and `/success.html` are noindex/no-store by design.
- The changelog strip, pricing cards, and discount form all degrade to
  static fallbacks when their APIs are absent — keep those fallbacks honest.
- `.env.local` (never committed) holds local Stripe keys for `vercel dev`.
- The store owner's launch checklist lives in LAUNCH.md (owner-only, not in
  the buyer archive); strategy notes in STRATEGY.md.
