HatchedDocs
Guides

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

Every 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

PathCacheUpdate behaviorWhen to use
cdn.hatched.live/widget.jsmax-age=300, must-revalidateAuto-updates with every deployDefault. Always-fresh.
cdn.hatched.live/v/<version>/widget.jsmax-age=31536000, immutableNever changesAudit-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.