Skip to main content

Contributing

Private repository

The ltv/cloudflare-workers-bootstrap repository is private. These notes apply to maintainers and invited contributors; users of the npm package don't need them.

Setup

Requires Bun 1.4.x (CI uses 1.4.2). The workerd end-to-end tests also need Node 24.

bun install

bun install also installs the git hooks: the pre-commit hook formats and lints staged files, and the commit-msg hook runs commitlint.

Before opening a pull request

CI runs these commands, so run them locally first:

bun run typecheck # TypeScript 7 (tsc --noEmit)
bun run lint # oxlint --type-aware
bun run format:check # prettier
bun run test:coverage # tests against real local D1/KV + coverage gate (every src file >= 90% lines/functions)
bun run build # tsdown
bun run check:package # publint + are-the-types-wrong
bun run check:size # gzip size budget per built file
bun run api:check # public API snapshot (etc/cwb.api.d.ts) is up to date
bun run test:e2e # builds, then runs examples/basic-worker in real workerd (node --test)

If you intentionally change the public API, run bun run api:update after building and commit the updated etc/cwb.api.d.ts. A diff in that file is a public API change.

main accepts squash-merged pull requests only. The PR title becomes the commit message and decides the release version. CI, end-to-end and security checks (bun audit, TruffleHog, Semgrep) must pass first.

Conventions

  • Code: kebab-case file names, files under 200 lines, the @/* import alias, and explicit return types on public generic APIs.
  • Tests: every bug fix or feature needs a test. Datasource and cache tests run against real local bindings, not mocks.
  • Public API changes: update README.md and the relevant files in docs/. Breaking changes also need a migration guide entry; deprecations follow the support policy.
  • ESLint isn't used: typescript-eslint doesn't support TypeScript 7, so the repository uses oxlint with oxlint-tsgolint.

Commit convention

Conventional Commits, enforced three ways:

  • Locally: the commit-msg hook runs commitlint.
  • In CI: commitlint checks every commit in the pull request.
  • PR title: a check validates it, because the squash commit on main uses it.
type(scope)!: subject

body

BREAKING CHANGE: description

Types: feat, fix, perf, refactor, docs, test, build, ci, chore, style, revert.

Releases

Releases are fully automated; never bump package.json by hand.

  1. Squash-merge a pull request with a conventional title.
  2. release-please opens or updates chore(main): release x.y.z with the version bump and CHANGELOG.md.
  3. Merging the release PR tags the release and publishes to npm.
Commit on mainBump before 1.0Bump from 1.0
fix:, perf:, revert:patchpatch
feat:patchminor
feat!: or a BREAKING CHANGE: footerminormajor
docs, test, ci, chore, refactor, build, stylenonenone