15 KiB
HDR Web Plugin Agent Manual
Scope
This file applies to the entire repository.
Use Chinese when talking with the project owner unless they ask for another language. Keep implementation work simple, direct, and narrowly scoped. Reuse existing files, functions, scripts, media conventions, and tests before adding new structure.
Follow higher-priority system and developer instructions first. When replacing an implementation, remove the old path in the same change so the repository does not keep parallel implementations.
Product Summary
HDR Web Plugin is a static Cloudflare Pages site plus a drop-in JavaScript file that makes ordinary pages present a black-stage HDR media layer, optional HDR text assets, and a small runtime UI.
Current public site:
- Production Pages project:
hdr-web-plugin-demo - Production URL:
https://hdr-web-plugin-demo.pages.dev/ - Main plugin URL:
https://hdr-web-plugin-demo.pages.dev/dist/hdr-web-plugin.js?v=0.6.2 - Real starfield demo URL:
https://hdr-web-plugin-demo.pages.dev/demos/fireworks.html?v=0.6.9
Important version facts:
package.jsonversion:0.6.2dist/hdr-web-plugin.jsbanner version:0.6.2- Current CSS cache query version used by pages:
0.6.9 - Current starfield asset:
media/hubble-westerlund-2-hdr.png
The route demos/fireworks.html is kept for URL compatibility with earlier demos, but its current product meaning is a real astronomy starfield HDR image demo. Do not reintroduce the old WebGL fireworks path unless the owner explicitly asks for a separate new demo. If a replacement is made, delete stale scripts, markup references, and generated copies.
Repository Map
src/hdr-enhance.js: canonical plugin source.dist/hdr-web-plugin.js: generated plugin bundle with the version banner. Do not edit this file by hand; runnpm run build.index.html: one-page landing page for installation, API notes, assets, and demo links.demos/*.html: standalone demos that use the same plugin and site chrome.styles/demo.css: shared landing/demo CSS. Bump query strings in HTML when changing this file.media/: committed HDR media assets and generated visual assets.scripts/build-dist.mjs: copiessrc/hdr-enhance.jsintodist/hdr-web-plugin.jswith a banner.scripts/generate-hdr-media.mjs: creates HDR video demo media.scripts/generate-hdr-image.mjs: creates landing prism HDR image.scripts/generate-hdr-wordmark.mjs: creates HDR PNG text/wordmark assets.scripts/generate-real-starfield-image.mjs: downloads the ESA/Hubble source image and writes the HDR PNG starfield.test/*.mjs: Node test suite covering plugin behavior, landing page structure, HDR metadata, and demo constraints._headers: Cloudflare Pages static header rules. This file must be copied into the upload/build output.public/: generated Cloudflare Pages upload bundle. It is intentionally ignored by Git; regenerate it before deployment.
Engineering Rules
- Prefer the smallest working change that solves the current request.
- Do not add abstractions for hypothetical future needs.
- Add an abstraction only when it removes current duplication or matches an existing local pattern.
- Do not keep old and new implementations side by side after a replacement.
- Never revert user work unless the user explicitly asks.
- Use
rgorrg --filesfor searching. - Use
apply_patchfor manual source edits. - Avoid broad refactors while changing visual design, media, or deployment docs.
- Update tests when changing behavior, generated media expectations, file structure, or production operations.
- Update this
AGENTS.mdwhen production URLs, deployment commands, cache strategy, HDR asset formats, or ownership rules change.
Local Development
Install and build:
npm run build
npm test
Run a local static server:
python3 -m http.server 4173
Open locally:
- Landing page:
http://localhost:4173/ - Starfield demo:
http://localhost:4173/demos/fireworks.html?v=0.6.9
The test script runs npm run build in pretest, so dist/hdr-web-plugin.js should stay aligned with src/hdr-enhance.js after every test run.
HDR Implementation Notes
Real HDR on macOS depends on the full chain:
- HDR-capable Apple display or external HDR display.
- macOS display setting with HDR enabled where applicable.
- Browser path that supports HDR media rendering.
- Black page background so bright HDR media has visible contrast.
- Media encoded with HDR metadata, usually BT.2020 primaries and SMPTE ST 2084/PQ transfer.
- Avoid CSS filters, opacity stacks, or canvas readbacks on true HDR assets unless verified. These can flatten or tone-map the output.
For high-brightness text, prefer HDR PNG assets produced by scripts/generate-hdr-wordmark.mjs instead of normal DOM text. Ordinary CSS text is normally SDR-composited by browsers and will not visibly exceed SDR white in the same way as an HDR image/video layer.
Current HDR PNG checks expected by tests:
pix_fmt=rgba64becolor_transfer=smpte2084color_primaries=bt2020- PNG bit depth:
16 - PNG color type:
6(RGBA)
Use ffprobe to inspect a media asset:
ffprobe -v error -select_streams v:0 \
-show_entries stream=pix_fmt,color_transfer,color_primaries \
-of default=nw=1 media/hubble-westerlund-2-hdr.png
Starfield Asset Policy
The real starfield demo uses the NASA/ESA Hubble Westerlund 2 image through the ESA/Hubble archive source URL embedded in scripts/generate-real-starfield-image.mjs:
https://esahubble.org/media/archives/images/large/heic1509a.jpg
The generator creates media/hubble-westerlund-2-hdr.png at 2560x1440. Keep that size unless there is a clear reason to change it; it gives an immersive full-screen result while keeping the file size manageable for Pages.
The visible credit must remain available on the demo page:
Westerlund 2 · NASA, ESA, the Hubble Heritage Team
Do not replace the real starfield with abstract particles, shader bloom, simulated fireworks, gradients, or decorative blobs when the user asks for a true starfield.
Generated Bundle Sync
Cloudflare Pages deploys from a static directory. In this repository, use public/ as the local upload bundle.
Regenerate public/ from source after tests pass:
rm -rf public
mkdir -p public
cp -R index.html _headers dist styles demos media public/
Do not edit files inside public/ directly. If public/ contains a stale file after a feature replacement, regenerate it from source so old paths disappear.
Cache Strategy
This project uses long cache headers for versioned static assets and no-cache headers for HTML.
Current _headers intent:
/dist/*: immutable long cache./styles/*: immutable long cache./media/*: immutable long cache./*.htmland/: revalidate.
Because dist/, styles/, and media/ are immutable in production, update HTML query strings when changing CSS or plugin JS. For media changes, either use a new filename or update every URL/query string that points at the changed asset.
Cloudflare Pages also has deploy-level caching behavior, so never assume a changed asset path will refresh immediately if the URL did not change.
Official references:
- Cloudflare Pages headers:
https://developers.cloudflare.com/pages/configuration/headers/ - Cloudflare Pages serving and cache behavior:
https://developers.cloudflare.com/pages/configuration/serving-pages/
Production Deployment Manual
Use this checklist for every production deployment.
- Inspect repository state.
git status --short --branch
git remote -v
If unexpected modified files exist, inspect them and preserve user work. Do not reset the worktree.
- Run the full test suite.
npm test
- Verify important HDR media metadata when media changed.
ffprobe -v error -select_streams v:0 \
-show_entries stream=pix_fmt,color_transfer,color_primaries \
-of default=nw=1 media/hubble-westerlund-2-hdr.png
ffprobe -v error -select_streams v:0 \
-show_entries stream=pix_fmt,color_transfer,color_primaries \
-of default=nw=1 media/hdr-wordmark.png
Expected output includes rgba64be, smpte2084, and bt2020.
- Regenerate the Pages upload bundle.
rm -rf public
mkdir -p public
cp -R index.html _headers dist styles demos media public/
- Deploy with Wrangler.
Use the latest locally verified Wrangler if available. This command shape is known to work for this project:
npx --yes wrangler@4 pages deploy public \
--project-name=hdr-web-plugin-demo \
--branch=main \
--commit-message="Deploy HDR Web Plugin" \
--commit-dirty=true
If the repository has no commit yet, Wrangler can print a Git warning about HEAD. If the command still returns a successful Pages deployment URL, treat the Git warning as non-fatal and continue verification.
- Verify production URLs.
curl -I https://hdr-web-plugin-demo.pages.dev/
curl -I https://hdr-web-plugin-demo.pages.dev/styles/demo.css?v=0.6.9
curl -I https://hdr-web-plugin-demo.pages.dev/dist/hdr-web-plugin.js?v=0.6.2
curl -I https://hdr-web-plugin-demo.pages.dev/media/hubble-westerlund-2-hdr.png
Open these URLs in a browser after deployment:
https://hdr-web-plugin-demo.pages.dev/https://hdr-web-plugin-demo.pages.dev/demos/fireworks.html?v=0.6.9
Check that:
- The landing page is one coherent page, not split into mismatched subpages.
- Navigation styling is consistent.
- Backgrounds intended for HDR contrast are true black.
- The starfield demo is a real full-screen astronomy image.
- No old
fireworks-webgl.jsscript is loaded. - The console has no JavaScript errors.
- Record the outcome.
If working in Git, commit the source changes after verification. If a Gitea remote is configured, push the branch.
Rollback Manual
For urgent production rollback:
- Prefer the Cloudflare Pages dashboard rollback for the project
hdr-web-plugin-demowhen an immediately previous deployment is known good. - If using CLI, inspect available deployments first:
npx --yes wrangler@4 pages deployment list --project-name=hdr-web-plugin-demo
- Do not guess an unsupported rollback command. If the CLI rollback path is unclear, use the dashboard.
- For source-controlled rollback, use
git revert <bad-commit>, runnpm test, regeneratepublic/, deploy the reverted source, and verify production.
Never use git reset --hard or force-push as a production rollback unless the owner explicitly asks for that exact operation.
Incident Runbooks
Stale CSS, JS, Or Media
Symptoms:
- Production looks like the previous version.
- Browser loads an old CSS/plugin/media file.
- Local preview is correct but Pages is stale.
Actions:
- Confirm the HTML references the intended versioned URL.
- Bump the CSS or plugin query string, or use a new media filename.
- Run
npm test. - Regenerate
public/. - Deploy again.
- Use
curl -Iand browser DevTools Network to confirm the new URL is served.
HDR Is Not Visibly Strong
Symptoms:
- User reports that text or media still looks SDR.
- Bright image layer looks stronger than text.
Actions:
- Confirm the page background is pure black where HDR should be judged.
- Confirm macOS and the target display have HDR enabled.
- Confirm browser support with
matchMedia('(dynamic-range: high)'). - Verify media metadata with
ffprobe. - Avoid normal DOM text for peak HDR claims; use generated HDR PNG text assets.
- Check CSS for
filter, opacity, blend modes, canvas rendering, or parent effects that can flatten HDR. - If using a new text asset, regenerate it through
scripts/generate-hdr-wordmark.mjsor add a focused generator script and test its metadata.
Page Is Blank Or Broken
Actions:
- Open browser DevTools Console and Network.
- Check that all referenced assets exist in source and in regenerated
public/. - Run
rgfor missing filenames and stale references. - Run
npm test. - Verify that HTML paths work from both local root and Pages root.
Performance Regression
Actions:
- Prefer static HDR image/video layers over custom per-frame WebGL for showcase backgrounds.
- Remove unnecessary continuous animations.
- Keep demo pages full-screen but visually simple.
- Avoid large blur filters, huge box shadows, and many animated particles.
- Test on the target Mac browser before deployment.
Wrangler Or Cloudflare Auth Problem
Actions:
npx --yes wrangler@4 whoami
npx --yes wrangler@4 login
If login is required, ask the owner to complete the browser auth flow. Do not commit .wrangler/.
Gitea Alignment Manual
This repository must be kept commit-ready. Before committing:
git status --short --branch
npm test
Current Gitea repository:
- Web:
https://git.aiot.ml/kanshan/HDR - Git remote:
https://git.aiot.ml/kanshan/HDR.git - Default branch:
main tealogin profile:git-aiot
Use the HTTPS remote for this repository. The Gitea SSH endpoint on port 2222
may be unavailable from the current network, while HTTPS push works through the
tea credential helper. Ensure the helper is installed before pushing:
tea logins helper setup
git remote -v
git push -u origin main
Recommended source files to commit:
AGENTS.md.gitignoreREADME.md_headerspackage.jsonindex.htmlsrc/dist/styles/demos/scripts/media/test/
Do not commit:
.wrangler/public/node_modules/- temporary media source downloads under
media/.*-source.*
If git remote -v is empty, a Gitea push cannot be completed from this machine until the remote URL is configured.
Configure a Gitea remote only with the exact owner-provided URL:
git remote add origin <gitea-repository-url>
git push -u origin main
To create a new repository with the configured tea account, first verify that
the name is unused, then create an empty server-side repository without README
initialization so the local history remains authoritative:
tea repos list --owner kanshan
tea repos create --name <repository-name> \
--description "<repository-description>"
git remote add origin https://git.aiot.ml/kanshan/<repository-name>.git
tea logins helper setup
git push -u origin main
If a remote already exists:
git fetch origin
git status --short --branch
git push origin main
Do not force-push to Gitea unless the owner explicitly requests it.
Pre-Final Agent Checklist
Before telling the user the work is done:
- Run
npm test. - Confirm
git status --short --branch. - Confirm old replaced paths are gone with
rg --files. - If production changed, verify the deployed Pages URL.
- If Git was requested, commit locally and push only when a remote is configured.
- Report any missing external state plainly, especially missing Gitea remote or Cloudflare auth.