8c5976ffd3 URGENT: fingerprint docs client bundle to fix mixed-version cache regression (PAP-16990) (#90)
## Urgent hotfix — mixed-version asset cache regression (PAP-16990)

Restores reliable navigation on https://docs.paperclip.ing/ without
undoing the PAP-16670/#87 server-render + single-H1 SEO/AEO work.

### Root cause
The server-render change shipped new HTML that removed `#loading` /
`#error-state`, but every generated route still loaded the client bundle
from a **stable URL**: `<script src="app.js" defer>`.
Cloudflare/browsers cache `/app.js` for up to ~4h independently of the
HTML, so a returning visitor could pair freshly-revalidated new HTML
with a **pre-merge cached `app.js`**. The old click path looked for the
removed elements, threw before render, hid the homepage, and left a
blank `#main` (no URL update). Forced refresh recovered — not
acceptable.

CSS was never part of this: it is inlined into every page and travels
with the (revalidating) HTML. `content.json` is byte-identical
prod↔preview.

### Fix (narrow cache-bust, no rollback)
1. **Content-fingerprint the client bundle.** Emit `app.<hash>.js` (+
`styles.<hash>.css`) and rewrite the shell so *every* route references
the exact build's asset URL. A changed bundle gets a brand-new URL no
cache can satisfy with stale bytes — closes the mixed-version window in
**both** directions. No unversioned `/app.js` is emitted, so a stale
cache has nothing to pin.
2. **`_headers`:** fingerprinted JS/CSS cached `immutable` (1y); HTML
routes (`/`, `/*/`) and `content.json` set `max-age=0, must-revalidate`.
3. `inlineReleaseStyles` now matches the fingerprinted stylesheet link
so CSS stays inlined.

### Before / after
```
- <script src="app.js" defer></script>          # stable URL — cacheable across versions
+ <script src="app.1b669c8d0aec.js" defer></script>   # content-hash URL — cache miss on any change
```
`_headers` (new):
```
/app.*.js
  Cache-Control: public, max-age=31536000, immutable
/
/*/
  Cache-Control: public, max-age=0, must-revalidate
/content.json
  Cache-Control: public, max-age=0, must-revalidate
```

### Verification (local build, base path `/`)
- `npm run docs:build` → emits `app.1b669c8d0aec.js`,
`styles.9e3f24983c72.css`; **184/185** HTML files reference the
fingerprinted bundle (185th is the scriptless `404.html`); **no** bare
`app.js`/`styles.css` file or reference remains.
- `npm run docs:test:asset-fingerprints` ✅ (new) — proves the URL is the
content hash of the served bytes, changes on any content change, is
referenced identically by root + interior routes, has no unversioned
sibling, and the cache headers are present.
- `npm run docs:test:static-routes` ✅ — single-H1 interior pages, no-JS
server-render, homepage manifest completeness, 404 separation, root +
`/paperclip-docs/` builds.

### Remaining (post-merge, needs a real browser on the live domain)
Chromium can't launch in the CI/agent sandbox (missing system libs), so
**cold + returning/cached** browser smoke on https://docs.paperclip.ing/
must be run after merge → redeploy from `main`. Checklist: cold load,
homepage-card nav (URL updates, one H1, no blank), interior↔interior,
Back/Forward, All Docs, search, 404, and a returning/cached session
(prior `/app.js` in cache).

Does **not** touch the SKILL.md formatting PR (PAP-16980), per the
issue.

Co-authored-by: DevRel Gemini <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-10 13:41:27 -07:00
2026-04-30 11:04:18 -05:00

Paperclip Docs

Source for the Paperclip documentation site — user guides, API and CLI reference, adapter docs, and deployment notes.

Read the docs: https://docs.paperclip.ing/

What's inside

  • Guides — Getting started, core concepts, and day-to-day usage.
  • API reference — Control-plane endpoints and payload schemas.
  • CLI reference — paperclip command surface.
  • Adapters — Plugin authoring and the integrations catalogue.
  • Deploy — Self-hosting, upgrades, and operational guidance.

The site is a single static shell that renders the Markdown files in docs/ directly — no framework, no build step required to read the raw pages.

Build and deployment

Build a release bundle locally with:

npm run docs:build

Cloudflare Pages is connected directly to paperclipai/paperclip-docs through GitHub. There is no normal Wrangler publish step for this repo:

  • Pushes to main deploy production at https://docs.paperclip.ing/.
  • Pushes to other branches create Cloudflare Pages preview/canary deployments.
  • Canary URLs are created by Cloudflare for each deployment, for example https://92b9a99c.paperclip-docs-74t.pages.dev. Use the URL shown in the Cloudflare Pages deployment row or GitHub deployment/check for the pushed branch and commit.

Contributing

Spotted a typo, a broken link, or something that could be clearer? There are two easy paths, both linked from the footer of every docs page:

  • Suggest an edit — opens the underlying Markdown file in GitHub's web editor. Make the change and submit a PR without leaving the browser.
  • Report an issue — opens a prefilled Docs feedback issue with the page URL already attached.

For larger changes, fork the repo and open a PR against main. Screenshots live under docs/user-guides/screenshots/{light,dark}/ and should be provided in both themes when replacing UI captures.

Community

License

Copyright (c) 2026 Paperclip Community.

The Paperclip software is open source — see the main paperclip repository for its license.

The documentation in this repository is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0). You may read and share it for non-commercial purposes with attribution. Commercial use of any kind requires prior written permission from the copyright holders. See LICENSE for the full text.

S
Description
Paperclip documentation
Readme CC-BY-4.0
491 MiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 91.1%
CSS 7.1%
HTML 1.6%
Shell 0.2%