# Deploying quack

quack is a static Vite build: `npm run build` writes `dist/`, and Cloudflare
serves that directory as a Workers static-assets site. No server, no bindings.

## What goes up

`dist/` and nothing else:

```
index.html          entry point, loading card and title-card styles
assets/index-*.js   the bundled pond (content-hashed by Vite)
assets/index-*.js.map  its source map (production builds always write one)
pond-loader-*.jpg   the loading card's opening-pond stills (from public/)
quack_audio.wasm    the Rust audio stage (built from duck-pond, see docs/audio.md)
quack-audio-worker.js   renders the stage off the main thread
quack-audio-worklet.js  plays the rendered blocks
quack-source.zip    the fifth title card's source download (generated)
```

`node_modules/`, `temp/`, local credential files and the Rust study clone never
leave the machine. `dist/` is git-ignored; it is rebuilt from the working tree.
The source *does* ship: `npm run build` writes `public/quack-source.zip` (and
copies it into `dist/`) for the fifth title card, and the source maps expose the
bundled modules. If `SOURCE.src_url` in `src/config.ts` is filled in, the card
opens that URL instead; the zip is still generated.

## One-time setup

Node 20.19+ or 22.12+ (what Vite needs), then:

```sh
npm install
npm exec --yes wrangler@latest -- login
```

`login` opens the browser once and stores an OAuth token. Check who Wrangler is
going to deploy as:

```sh
npm exec --yes wrangler@latest -- whoami
```

If a `CLOUDFLARE_API_TOKEN` is already exported, Wrangler picks it up instead and
`login` is not needed.

## Deploying an update

```sh
npm run build
npm exec --yes wrangler@latest -- deploy ./dist --name quack --compatibility-date 2026-10-19
```

Wrangler reads `dist/`, uploads the assets that changed, and prints the live URL
and a version ID. The URL does not change between deployments.

- `--name quack` is required for a static-assets deploy; there is no
  `wrangler.toml` in this repo, by design.
- `--compatibility-date` is the Workers runtime date stamped on the deploy. Bump
  it when you want newer runtime behaviour; the date above is the first
  deployment's.
- The JS bundle and its source map are content-hashed by Vite, so `index.html`
  always names the right build. The two loading JPEGs, the audio
  worker/worklet/wasm and `quack-source.zip` keep fixed names; the zip is
  regenerated by every `npm run build`. Rename any of them (and update
  `index.html`, `src/audio.ts` / `public/quack-audio-worker.js`, or
  `src/hints.ts`) if you need to defeat a long cache.
- Rebuild the audio stage only when the Rust bridge changes: `npm run audio`
  (see `docs/audio.md`). Normal front-end deploys use the committed
  `public/quack_audio.wasm`.

## Rolling back

```sh
npm exec --yes wrangler@latest -- deployments list --name quack
npm exec --yes wrangler@latest -- rollback <version-id> --name quack
```

The list prints the version ID to pass to `rollback`.

## Temporary / no-account preview

For a throwaway URL without deploying under an account:

```sh
npm run build
npm exec --yes wrangler@latest -- deploy ./dist --name quack --temporary --compatibility-date 2026-10-19
```

That only works while Wrangler is logged out — it refuses `--temporary` when an
account is connected. It returns a `workers.dev` URL plus a claim URL; the
deployment is removed after 60 minutes unless claimed. For this project, prefer
the normal deploy above.

## Checking a deploy

Open the URL Wrangler printed on a phone as well as a desktop — the pond is
mobile-first. Workers assets can take a few seconds to propagate; a 404
immediately after a deploy usually means: wait and reload.

## Re-shooting the loading card

The card's backdrop is a still of the opening pond, so it is stale whenever the
pond's look changes:

```sh
npm i --no-save sharp        # only this script needs it
npm run dev                  # note the URL it prints
node scripts/loader-shot.mjs <dev-url> public/pond-loader-portrait.jpg 430 932 2 480 50
node scripts/loader-shot.mjs <dev-url> public/pond-loader-landscape.jpg 1440 900 1 880 50
```

The script pauses the world, hides the flock and the particles, and writes a
progressive JPEG. Raw PNGs stay in `temp/loader/`. Rebuild and redeploy after.

## Notes

- `.wrangler/` is Wrangler's local cache (git-ignored); deleting it is safe.
- `wrangler deploy` also accepts a single `.html` file, but this project wants
  the folder so the hashed JS and the card images go up together.