# sub3 example on Cloudflare Workers

The [Node example](../node/README.md) as a Worker, against the **sub3 sandbox** (Arc Testnet, free test USDC). The
routes are the same file (`../node/app.mjs`); the pages are `../node/public`; the ledger is the SQLite of one
Durable Object per environment and product, so receipts are credited once and credits are never spent twice.

| File             | What it does                                                                                       |
| ---------------- | -------------------------------------------------------------------------------------------------- |
| `wrangler.jsonc` | Static pages from `../node/public`; `/api/*` and `/.well-known/sub3.json` go to the Worker; vars   |
| `worker.mjs`     | Sends those requests to the `Ledger` Durable Object, which runs `createApp` on `ledgerOn(storage)` |

## Deploy

1. Create your handle and product yourself **in the sandbox dashboard**, https://sub3.dev/sandbox/dashboard, with
   your own wallet (free test USDC from https://faucet.circle.com). Any item keys work: the app reads them from
   the API.
2. Set `SUB3_PRODUCT` and `APP_ORIGIN` in `wrangler.jsonc`. `APP_ORIGIN` is the one origin users sign in on,
   exactly: your `https://…workers.dev` address or your custom domain, not both. Session tokens are issued to
   that origin only, so turn off the other address (`workers_dev: false` with a custom domain) or redirect it.
3. Deploy:

   ```sh
   cd examples/cloudflare
   npm run setup        # installs wrangler here and jose in ../node
   npx wrangler login
   npm run deploy
   ```

4. Your logo: the Worker serves `/.well-known/sub3.json` naming your merchant, so sub3's sign-in and checkout
   pages opened from it show `../node/public/logo.svg` (replace it with your own). Leave the merchant's website
   as it is: a product site never needs it changed.

`npm run dev` runs it locally (`wrangler dev`). To go live, create the same handle and product on
https://sub3.dev/dashboard and set `SUB3_ENVIRONMENT` to `production`; sandbox and production never share
purchases.

One Durable Object serves every user of the product: simple and strictly consistent, and enough for a demo or a
small app. For heavy traffic, use one Durable Object per user (`idFromName(user)`), since each user's receipts,
credits and allowance are independent.
