Reference

Versioning

One major across every package, what a version change means, and how a release is cut.

Every Minnow package shares a major version and moves independently inside it. The major is the compatibility line: any @minnowdb/client@0.x works with any @minnowdb/core@0.x, whichever minors the two happen to be on.

npm install @minnowdb/core @minnowdb/client

The client and the devtools console are built on the engine's published primitives, and a change that breaks that contract is a major change by definition. So each package depends on its siblings by a range that spans the major and stops at it:

"dependencies": { "@minnowdb/core": ">=0.1.0 <1.0.0" }

The ceiling is the compatibility line, and npm refuses a mixed-major install on its own. The floor is the sibling release this package was built against — when the devtools start using something the engine added in 0.4.0, their next release says >=0.4.0 and npm resolves an engine that has it. Below the major, a fix to the console does not drag the engine's version along with it.

What 0.x means

Minnow is in 0.x, and the usual 0.x rule applies: breaking changes can land in a minor release. Pin exact versions in an application, and read the release notes before moving from 0.1 to 0.2.

A change is breaking when it is one of these:

  • The API. An export removed or renamed, a signature narrowed, or a default changed.
  • SQL. A form that used to run and no longer does, or one that runs and now answers differently. Additions to the feature matrix are not breaking.
  • Stored data. A database written by the old version that the new one cannot open.

From 1.0 onwards these move the major version — every package's, together — and minor releases stay additive.

The block format has its own version

The version on the package describes the code. The bytes in IndexedDB carry a separate BLOCK_FORMAT_VERSION, and a snapshot file carries SNAPSHOT_FORMAT_VERSION. They move on their own schedule — most package releases do not touch them.

Every released format version keeps a frozen database in packages/core/format-fixtures/, opened and queried on every test run, so a change that would make an existing database unreadable fails in CI rather than in an application. See Testing for how that suite works.

How a release is cut

One command writes the versions, the dependency ranges between them, and the lockfile:

npm run version:set -- minor @minnowdb/core   # one package, inside the shared major
npm run version:set -- major                  # every package to the next major, together

Then commit and push. That is the whole release:

npm run check:release   # optional locally; CI runs the same gate
git commit -am "Release core 0.2.0" && git push

Publishing is driven by the versions in the manifests, not by a tag or a command. When that commit's CI run goes green, .github/workflows/release.yml publishes every package whose version npm does not already have and tags each one @minnowdb/core@0.2.0. A push that changes no version publishes nothing, and a rerun after a failure is safe, because the registry decides what has already shipped.

There is no npm token in the repository. npm is configured to trust that workflow in this repository, and hands it a credential that lives for the length of one publish — which is also what signs the provenance attestation you can see on each version's npm page. Nothing expires and there is nothing to rotate. It is configured once per package, in the package's settings on npm, and a package has to exist before it can be configured: the first release of a new package is published from a machine with npm run release:publish, and every release after it from CI.

Two things are checked before anything leaves the machine. npm run version:check proves the workspace agrees with itself — matching majors, ranges that span them, and a docs version that matches the engine — as the first step of both npm run check and CI. And the publish refuses a tarball carrying anything that is not part of the package: tests compile into dist beside the code, and files has to exclude them.

Where each version's documentation lives

The documentation describes the engine, so it is versioned with @minnowdb/core: v0.1 while Minnow is in 0.x, where a minor can break things, and v1, v2 from 1.0 onwards.

URLWhat it serves
minnowdb.com/docs/…The current release. A link written here never goes stale.
minnowdb.com/v0.1/docs/…0.1.x, frozen at its tag, for as long as it is worth keeping.

The picker at the top of the docs sidebar moves between them and keeps you on the same page. It reads /versions.json from the site's root rather than the copy compiled into the build, so an archived version still lists releases that did not exist when it was frozen.

Everything under an archived prefix is versioned with it: its search index, its markdown and llms.txt, and every link between its pages. Archived pages also carry noindex, so a search engine offers the current documentation first. The playground and the benchmarks are not archived — they always run the current release.

An archive is the same site built from the tag with a base path:

git worktree add ../minnow-v0.1 v0.1.0
cd ../minnow-v0.1 && npm ci
SITE_BASE_PATH=/v0.1 npm run site:build

apps/site/out/ is then deployed at that prefix, and the version is added to the archived list in apps/site/public/versions.json on main. On Vercel that means a project of its own, with the main site rewriting /v0.1/:path* to it — a static export has no server to route with, so the prefix has to come from the platform.

On this page