BORROWDALEJS / PROJECT
Contributing to BorrowdaleJS
Contributions can improve code, documentation, examples, accessibility or bug reports. Start with a focused change and include enough context for someone else to check it. Everyone taking part follows the code of conduct.
Set up the workspace
Development uses Node.js 24 (see .nvmrc). Clone the repository, then run:
nvm use
npm ci
npx playwright-core install chromium firefox webkit # once: the parity tests render in all three
npm run build
npm test
npm run typecheckThe parity tests draw every golden in headless Chromium, Firefox and WebKit and compare the output
with Node's byte for byte. They fail, rather than skip, when a browser is not installed. Continuous
integration runs the same steps on Node.js 22, 24 and 26 for every pull request. npm test
and npm run typecheck cover the website too. To work on it, run npm run site to preview it and
npm run site:build to build it and check the static pages.
| Path | What it holds |
|---|---|
packages/core, packages/fills, packages/text, packages/charts |
The published packages: src/, test/, and a README.md that is the package's reference |
packages/*/test/golden/ |
The golden corpora: corpus.json lists the inputs, goldens.json the expected output |
apps/examples |
Runnable examples that load the built packages |
apps/site |
The website: the guides in content/, and pages built from the package READMEs and the golden corpora |
scripts/ |
Recording the goldens, generating the bundled font modules, and preparing the manifests the release publishes |
.changeset/ |
Release notes waiting for the next release |
Report a bug
Open an issue with the bug form. Give the smallest input that shows the problem, the output you expected and the output you got, the package version or commit, and the runtime or browser and operating system. Include the seed when a drawing differs. Remove private data and credentials before posting.
Report a security problem privately instead, as the security policy describes.
Propose a change
For a new feature, or a change to an API or to drawn output, explain the use case in an issue first. Small fixes and documentation improvements can go straight to a pull request.
Making a change
Keep drawings deterministic
The same input must give the same drawing, byte for byte, on every render, in Node and in every
browser. Drawing code therefore never reads the clock, a random source, the locale or the time zone,
and never calls a Math function whose result the engine is free to approximate. Use
@borrowdale/core/math for sin, cos and log, and take randomness from the seed. The test
guard in packages/core/test/support/forbid-unportable-calls.ts makes such calls throw while a
golden is drawn.
Inputs that would make drawing hang or run out of memory must fail with a named error instead, and the limit must be documented in the package README.
Change drawn output on purpose only
Golden output changes only when a drawing is meant to change. Regenerate it with npm run goldens,
then read the diff of goldens.json: replacing a baseline is not a substitute for finding out why a
test failed. A change to drawn output is visible to every user, so it needs a changeset (below).
Write tests that read as data and checks
- Every bug fix comes with a test that fails without the fix.
- A test body holds its data and its checks only: no loops, conditionals or inline functions. Shared
data and helpers are defined beside the tests, at module level, and a table of cases goes through
it.each. - A comment that describes a test sits directly above it.
- A case that only some runtimes can run says so with
it.runIf, with a comment naming the runtimes.
Update the documentation with the code
The package README.md files are the reference documentation. Change them in the same pull request
as the behaviour they describe. Keep examples runnable, state limits as numbers, and say what has
been measured rather than what is expected.
Keep the website in step
The website renders the package READMEs and the guides in apps/site/content/ directly, and builds
its playground from the golden corpora in packages/*/test/golden/. Adding, renaming or removing a
golden case therefore also changes a public page and its URL. Keep the examples runnable, and use
public data whose source is stated.
Add a changeset for anything a package user can notice
Run npx changeset for a new or changed API, a change to drawn output, a new or changed error, or a
change to supported runtimes, and describe the change for someone reading the changelog. The four
packages share one version and are released together. While the version is 0.x, a breaking change
is a minor release and anything else a patch. Changes to tests, CI or development tooling need no
changeset.
After each merge to main, the Release workflow gathers the waiting changesets into a draft pull
request that sets the new version and writes each package's changelog. A maintainer releases by
approving its workflow runs, marking it ready and merging it; the workflow then tests that commit
and publishes the packages to npm. Merge it only after the Release run for the newest commit on
main has updated it: updating its branch from main does not apply new changesets, and a
changeset still waiting on the merged commit stops that release from being published. A changeset
names only packages that are published to npm, never the website or the examples; one that does is
never applied, and no release is published until it is deleted.
Commits
Subjects follow [scope] TYPE: sentence:
- scope:
core,fills,text,chartsorsite, orrepofor anything across the repository; - TYPE:
FEAT,FIX,REFACTOR,TEST,DOCS,STYLEorCHORE; - sentence: lower case, in the imperative, with no full stop at the end.
For example: [charts] FIX: end a free time axis no later than year 9999. Explain in the body why
the change is needed when that is not obvious from the diff. Keep each commit to one concern.
Pull requests
- Open pull requests against
main, and keep each one to a single change. - Fill in the template: what changed and why, the risks, and how it was tested.
- Continuous integration runs on every pull request: the Library workflow builds, typechecks and
tests on Node.js 22, 24 and 26, and the Website workflow builds and tests the website. Run
npm run build,npm run typecheckandnpm testyourself first, with the browsers installed, andnpm run site:buildtoo when the website changes. Runs for a pull request from someone outside the project wait until a maintainer approves them. After the merge, the Library workflow runs again unless the merge changes only documentation (Markdown, the licence files and the issue forms), and the Website workflow runs when what the website is built from changes, the package READMEs,CONTRIBUTING.md,CHANGELOG.mdand the licence files included. - A maintainer merges the pull request once it is approved.
What not to commit
Credentials or tokens, .env files, machine-specific paths, personal data, build output (dist/,
apps/examples/out/) and private working notes.
Licence
Contributions are licensed under the MIT License. Code or data taken from another project
needs a compatible licence, and its notice goes into the package's THIRD_PARTY_NOTICES.md (create
one, and list it in the package's files, if the package has none yet). The
bundled Excalifont files keep their own SIL Open Font License 1.1. Credits
for incorporated code, fonts and datasets are on the website's
License & credits page.
Contributors
The contributor history lists the people behind the project.