Pinning a widget version
Pin a frozen loader release with `cdn.hatched.live/v/<version>/widget.js` so your embed surface stays byte-for-byte stable across deploys.
By default, cdn.hatched.live/widget.js always serves the latest loader.
That's the right choice for most tenants: security patches and bug fixes
reach every partner page within a five-minute cache window without anyone
re-pasting a snippet.
If your integration needs a frozen contract — regulated industry, a long QA cycle, a slow change-management process — the loader also ships under pinned, immutable paths:
https://cdn.hatched.live/v/<version>/widget.jsEvery released loader version gets a directory under /v/<version>/
that contains the loader and every widget bundle it imports. Once
written, an object at one of these keys never changes content.
Quick comparison
| Path | Cache | Update behavior | When to use |
|---|---|---|---|
cdn.hatched.live/widget.js | max-age=300, must-revalidate | Auto-updates with every deploy | Default. Always-fresh. |
cdn.hatched.live/v/<version>/widget.js | max-age=31536000, immutable | Never changes | Audit-grade reproducibility, slow QA cycles. |
The unversioned path is the right answer 95% of the time. Use the pinned path only when you have a real reason — version pinning is opt-in because it freezes you out of security fixes that would otherwise reach your site automatically.
Pinning
Swap the src attribute:
<script
src="https://cdn.hatched.live/v/0.4.2/widget.js"
data-embed-token="EMBED_OR_SESSION_TOKEN"
defer
></script>
<div data-hatched-mount="buddy"></div>The loader's bundle base is URL-derived: a pinned loader pulls every
widget bundle from the same versioned tree, so a v/0.4.2/widget.js
install only ever fetches v/0.4.2/widget/v1/buddy-widget.min.js. There
is no way for a pinned page to accidentally load a newer widget bundle.
Verifying the pin took effect
The loader exposes its own version at runtime:
window.HatchedWidgets.version; // → "0.4.2"
window.HatchedWidgets.buildId; // → "abc123def456"Use these in:
- CI smoke tests — assert the deployed pin resolved to the expected version.
- Error reports — include both fields in any client-side error pipeline so you can correlate field bugs to a specific deploy.
Choosing a version
The loader version comes from apps/widgets/package.json, and each
release is mirrored to /v/<version>/ at deploy time. The
changelog lists each release. The latest
unversioned widget.js is always the head of main.
A safe pinning policy:
- Pin to the latest version when you cut a new tenant build. Don't pin once and forget — pinned loaders never receive security patches.
- Bump within ~30 days of a new minor. Older pins still serve forever (the objects are immutable), but you'll miss bug fixes.
- Subscribe to the docs changelog. Every loader release lists what changed, so you can review it before bumping your pin.
Rollback playbook
A pinned loader makes rollback trivial — flip the src attribute back
to a known-good version and redeploy your host page. Because the older
path is still served (immutable), the previous behavior comes back as
soon as the new HTML lands.
If you're on the unversioned path and need to roll back without waiting for a Hatched deploy, the pinned route is your escape hatch:
- <script src="https://cdn.hatched.live/widget.js" ...></script>
+ <script src="https://cdn.hatched.live/v/0.4.1/widget.js" ...></script>When the issue is resolved upstream, point the src back at the
unversioned path or the new version.
Staging and previews
The staging mirror at cdn.hatched.live/staging/widget.js exists for
testing against the staging API. It does not receive pinned version
mirrors — staging is short-lived and version freezing it would defeat
the purpose. Pin only in production.
What pinning does NOT pin
The loader pin freezes the client bundle: the loader, the widget bundles, the locale catalogs. It does not pin:
- API responses. The Hatched API ships forward-compatible changes (additive fields, new event types). Existing fields never change shape within a major version.
- CSS variables consumed by
themeVars. New--hw-*variables can appear in newer loader versions; pinning to an old loader version means you don't get them automatically. - Webhook event payloads. Webhook delivery is server-side. See webhook payloads for the contract.
If you need a fully end-to-end frozen surface, pin the SDK
(@hatched/sdk-js) and the loader together — both follow semver.