Contract versions and freezing
How the Collection Kit storefront contract is versioned, why a frozen version never changes, and how a new one is introduced and an old one retired.
A published Collection Kit bundle depends on the outside world: the storefront search API, the theme
block's window._mercury config, and the MERCURY.KIT manifest. Those dependencies are written down as
the kit contract, in api-types/src/kit-contract/v<N>, one directory per version:
| File | Declares |
|---|---|
search-api.ts | the routes a bundle calls, the query parameters it sends, and the response fields it reads |
theme.ts | the theme block's window._mercury config and <mercury-kit> attributes |
manifest.ts | the MERCURY.KIT shop metafield |
preview.ts | how the theme block loads a draft for preview (Mercury-internal; not in the public reference) |
The v1 contract reference is generated from these files.
Consumer-driven
A version declares only what the bundle reads. The server is free to add, reorder or change anything
the contract does not declare. Fields a bundle passes through without reading are typed as open
([key: string]: unknown) and are not guaranteed. This is narrower than the
storefront reference, on purpose: it is the promise, not the
whole surface.
Frozen
api-types/src/kit-contract/lock.json holds the sha256 of every file of every frozen version, and CI fails
if a frozen file changes, disappears, or gains a sibling. A frozen version is never edited, not even to fix
a comment.
The server is held to every supported version: its response types must satisfy each one (a server spec in CI), so a server change that would break a published bundle fails before it ships.
Introducing a version
- Copy
v<N>tov<N+1>and make the change there. - Freeze it:
npm --prefix api-types run kit-contract:freeze -- v<N+1>. - Point the kit at it (
collection-kit/host/src/contract.ts), so new builds record the new version. - Add the version's route responses to
KIT_RESPONSESinapi-docs/src/kit.tsand regenerate the docs (npm --prefix api-docs run generate); the docs check fails until you do, so a version can't ship undocumented. This site then lists it next to v1.
Retiring a version
Keep the server satisfying every supported version until no live store version was built against the old
one (each build records its contractVersion). Then remove it from supported in lock.json. The files
stay, and its reference page stays, marked retired.