SHOP compiles the public projection aggregate. Every USER is a SHOP. Every artifact has a price.
Pattern: {USER}/**/SHOP.md
Output: SHOP.json aggregate per USER
Gate: Deterministic, rerun-safe, drift-gated
```
```
| Field | Value | |||||
|---|---|---|---|---|---|---|
| title | {product name} | |||||
| type | BOOK | PAPER | DECK | CHAT | content | product |
| price | {amount} COIN | |||||
| route | /{route}/ | |||||
| seller | {USER principal} | |||||
| status | AVAILABLE | BETA | IN PROGRESS | |||
| synopsis | {1-2 sentence description} | |||||
| cover | {image path or omit for gradient} | |||||
| tags | {comma-separated keywords} | |||||
| audience | clinical | technical | business | general | ||
| domain | healthcare | finance | legal | realestate | governance | engineering |
| author | {creator name} | |||||
| edition | {version string: 1.0, BETA, etc.} |
Purchase supports dual payment:
Stripe Checkout session metadata carries: { event, product, service, amount_coin }. Webhook on checkout.session.completed triggers vault SALE event.
| Method | Flow | Event |
|---|---|---|
| COIN | API `/api/v1/spend` → buyer WALLET debit + seller WALLET credit | SPEND + MINT:WORK |
| Fiat | API `/api/v1/checkout` → Stripe Checkout → webhook → SALE event | SALE via stripe-sync |
SHOP is a composable service. Any page includes it via frontmatter. Same pattern as TALK.
{% include SHOP.html %} renders from page.shop + SHOP.json. ONE include. ONE script. ONE stylesheet.
SHOP.json per scope — compiled from SHOP.md Card tables. Shape: { products: [{ title, type, price, status, synopsis, route, cover, seller, tags, audience, domain, author, edition }] }
One card. One CTA.
| Element | Rule |
|---|---|
| Cover | Image or CSS gradient |
| Eyebrow | Type (BOOK, PAPER, DECK, CHAT) |
| Title | Product name |
| Synopsis | 1-2 sentence description |
| Tags | Comma-separated → rendered as pill chips |
| Badges | Audience + domain badges (monospace, token-colored) |
| Price | “{amount} COIN” or “Free” |
| CTA | “Add to Bag” (priced) or “Get” (free). Single button. |
Overlay (like TALK overlay). localStorage canonic-bag.
| Element | Rule |
|---|---|
| Items | Title + price per item. Remove button. |
| Total | Sum of COIN. |
| CTA | “Checkout” — one button. |
| Empty | “Your bag is empty.” |
| Method | Flow | Event |
|---|---|---|
| COIN | Confirm → /api/v1/spend → success | SPEND |
| Card | Stripe hosted → return with ?checkout=success | SALE via stripe-sync |
Single method selector. Not dual buttons per product.
Wallet lives in USER profile. SHOP reads WALLET.load() from base/wallet.js. Balance renders as subtle pill in SHOP header. Never reimplemented per page.
| Key | Values | Behavior |
|---|---|---|
| shop | true | Full catalog — product grid + bag + checkout |
| shop | inline | Inline product cards only (e.g. BOOKS page) |
| shop | false/omitted | No commerce UI |