This guide covers how to publish a new version of the web package to npm.
The release flow mirrors the existing Android (android-publish.yml) and
Swift (swift-publish.yml) workflows: a maintainer drafts a GitHub Release
with a platform-prefixed tag, a workflow runs in a protected environment, and
the package is published to npm with SLSA provenance.
cd platforms/web
pnpm version <new-version> --no-git-tag-versionUse a semver string. Examples:
4.0.0-alpha.2— next alpha prerelease4.0.0-beta.1— first beta4.0.0-rc.1— release candidate4.0.0— stable
--no-git-tag-version is intentional — the tag is created by the GitHub
Release UI in step 2, not by pnpm version.
Open a PR titled like chore(web): bump to 4.0.0-alpha.2. Get it reviewed
and merged into main. Wait for CI to be green on main.
Go to https://github.com/Shopify/checkout-kit/releases/new:
- Tag:
web/<version>— e.g.web/4.0.0-alpha.2. Create the tag frommain. - Title:
Web <version>— e.g.Web 4.0.0-alpha.2. - Notes: click Generate release notes and edit as needed. Highlight any breaking changes at the top.
- Set as a pre-release: ✅ check this box for any version containing
-alpha,-beta, or-rc. Leave unchecked for stable releases. - Set as the latest release: ✅ check for stable releases only. Don't check for prereleases.
Click Publish release.
The release event triggers .github/workflows/web-publish.yml. The job uses
the npm-web environment, which requires a maintainer to approve before the
publish actually runs.
You'll see a banner on the workflow run page: Review pending deployments. Click through and approve.
Once approved, the workflow:
- Validates the tag's version matches
package.json - Runs the full pipeline (lint, test, build, publint)
- Packs the tarball and prints its contents
- Publishes to npm with the appropriate dist-tag and SLSA provenance
After it's green, sanity check:
# For a prerelease (published under the `next` dist-tag):
npm view @shopify/checkout-kit@next version
# For a stable release:
npm view @shopify/checkout-kit versionThe package page on npm shows a Provenance badge linking to the workflow run that built it.
| Release type | Example tag | npm dist-tag | npm install resolves to |
|---|---|---|---|
| Stable | web/4.0.0 |
latest |
npm i @shopify/checkout-kit |
| Alpha / beta / rc | web/4.0.0-alpha.2 |
next |
npm i @shopify/checkout-kit@next |
| Manual override | any | whatever you pass to workflow_dispatch |
depends on tag |
The dist-tag is computed from three layered signals, in priority order:
- Explicit override — if you set the
taginput onworkflow_dispatch, that value wins (latest,next,beta, etc.). - GitHub Release's pre-release flag — if you checked "Set as a
pre-release" in the Releases UI, the workflow uses
next. - Defensive fallback from
package.jsonversion — if the version contains a-(a semver prerelease identifier like4.0.0-alpha.1), the workflow usesnextregardless of the release flag. This catches:workflow_dispatchruns (where there's no release event so the prerelease flag is empty)- Release events where the maintainer forgot to check the "pre-release" box for an obviously-prerelease version.
If none of the above applies (stable version, no override, not flagged as
pre-release), the workflow publishes under latest.
If you ever genuinely want to publish a -alpha.X version under latest
(rare — usually a mistake), use the tag workflow_dispatch input to
explicitly override.
The web/ tag prefix is required so the publish workflow knows the release
is for the web platform. Other platforms have their own prefixes:
- Web:
web/X.Y.Z - Android:
android/X.Y.Z - Swift: bare
X.Y.Z - React Native: TBD
You can trigger the workflow directly without creating a GitHub Release:
- Go to Actions → Web — Publish to npm → Run workflow
- Choose the branch (usually
main) - Optionally:
- Override dist-tag — e.g.
latest,next,beta,experimental - Dry run — runs everything except the final
npm publish. Use this to sanity-check the pipeline before a real publish, or to verify a misconfigured release.
- Override dist-tag — e.g.
The tag-vs-package.json validation is skipped on workflow_dispatch runs
(since there's no tag to validate against). Make sure package.json's
version is correct before running.
These are the one-time admin tasks required to enable Trusted Publishing. Documented here so this guide remains complete if the configuration ever needs to be re-created.
On https://www.npmjs.com/package/@shopify/checkout-kit:
- Settings → Trusted Publishers → Add a trusted publisher
- Configure:
- Provider: GitHub Actions
- Owner:
Shopify - Repository:
checkout-kit - Workflow filename:
web-publish.yml - Environment name:
npm-web
This tells npm to accept publishes that present an OIDC token from this exact
workflow file in this environment. No long-lived NPM_TOKEN is needed.
In the repo's Settings → Environments → New environment:
- Name:
npm-web - Required reviewers: 1+ maintainers from the package owners list
- Deployment branches: restrict to
main
The required-reviewer rule means every publish requires explicit human approval, even if the workflow somehow ran without authorization.
You created a GitHub Release tagged web/4.0.1 but forgot to bump
package.json first. Fix: bump in a PR (step 1 above), wait for it on main,
then delete and re-create the release with the same tag.
The npm Trusted Publisher configuration doesn't match the workflow. Common causes:
- Workflow file was renamed (npm trusts the exact filename)
- Environment name was changed
- Workflow is running on a fork PR (Trusted Publishing only works on the base repo)
Confirm the npm Trusted Publisher settings match the workflow's
environment: name: and the workflow's filename exactly.
npm doesn't allow republishing the same version, even if the previous
publish was incomplete. Bump to the next patch (e.g. 4.0.0-alpha.2 →
4.0.0-alpha.3) and run the release again. Don't try to delete and
re-publish.
Check that:
permissions: id-token: writeis present on the job (it is in the current workflow)- The job is running on a public GitHub-hosted runner (not self-hosted without OIDC support)
- The Trusted Publisher on npm is for the same workflow file path —
npm matches
web-publish.ymlexactly
The files field in package.json controls what's in the tarball:
LICENSE
README.md
package.json
dist/ (built JS, .d.ts, custom-elements.json, source map)
src/ (TypeScript source for consumers who want to read it)
Test files (*.test.ts), the playground (sample/), the consumer-test
harness, dev configs, and lockfiles are all excluded.
You can preview exactly what will be published before tagging a release:
cd platforms/web
pnpm pack --dry-run- Workflow:
.github/workflows/web-publish.yml - Pattern reference:
.github/workflows/android-publish.yml,.github/workflows/swift-publish.yml - npm Trusted Publishers docs: https://docs.npmjs.com/trusted-publishers
- npm Provenance docs: https://docs.npmjs.com/generating-provenance-statements