# 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.