The full contributor guide is at stackyard.sandobserver.com/docs/contributing.
Contributions are welcome within the constraints that keep Stackyard small and auditable. A change that breaks one of these will not be merged:
- One container: Nginx and the Node API run together under supervisord. No extra services, no database.
- No runtime dependencies: the API ships zero npm runtime packages; the frontend is vanilla HTML/CSS/JS with no framework and no build step.
- Server-side is CommonJS, the frontend is ES modules.
If a feature seems to need a dependency or a build step, open an issue first.
Run Stackyard from the working tree with Docker Compose 2.23 or later:
docker compose -f docker-compose.dev.yml watch
It serves http://127.0.0.1:8701. A saved file reaches the container within a
few seconds. A change under api/src or ui/widgets, or to a module the API
shares with the frontend, restarts the container. A change to the Dockerfile,
nginx or supervisord config rebuilds the image. Data is kept in .dev/.
Unit tests use Node's
built-in runner and need nothing installed; coverage and the browser tests use
the dev tooling in the root package.json.
An export whose name starts with _ exists for the tests and is not part of
what the module offers: _internals for functions reached directly, _reset*
for the hooks that clear state between tests. Anything else exported is API, and
is exported under the name it is defined with.
A change to behaviour lands with its tests, in the same pull request. New functionality needs tests for that functionality. A bug fix needs a test that fails without the fix. The coverage floor below enforces part of this rule; it is not the whole of it.
These are the checks CI runs, in the order it runs them. They are defined once,
in .github/actions/checks/action.yml, so the list here is the whole of that
action:
npm ci
node scripts/changelog-check.js
node scripts/bump-cache-busting.js --check
npm run paths:check
cd api && npm test
cd api && npx c8 check-coverage --lines 92
cd ui/test && node --test
cd test/repo && node --test
npm run lint
npm run format:check
npm run typecheck
npm run typecheck:ui
docker build -t stackyard:ci .
The end-to-end suite is a separate required check, in
.github/workflows/e2e.yml. It starts the image on a local port and runs the
browser specs against it:
npx playwright install chromium webkit
BASE_URL=http://127.0.0.1:<port> npx playwright test
CodeQL also runs on every pull request. A finding it reports has to be resolved before merge.
Trivy also scans the image built above. A HIGH or CRITICAL finding with a fix available fails the run. The threshold is in SECURITY.md.
-
changelog-check.jsverifies the structure ofCHANGELOG.md: the Keep a Changelog header, the six section names, a real date on every released version, descending versions, and a compare link per version. Structure fails the check. Style problems in[Unreleased], such as a rationale clause or a three-sentence entry, print as warnings on the pull request and do not fail it. Releasing is documented at Releasing. -
Changelog entries go in the pull request description, under Changelog, as
-lines below a### Fixed,### Addedor other Keep a Changelog heading. Do not editCHANGELOG.mdin a pull request. On merge, a workflow adds the entries to[Unreleased]. A pull request with no user-visible change leaves the section empty. -
bump-cache-busting.js --checkverifies that every/css/and/js/reference carries a?v=stamp. The release build recomputes the hashes, so write?v=1and never edit a stamp by hand. -
npm run typecheck:uitypechecks every module underui/jsfrom its JSDoc, with no build step and nothing emitted. It has to stay clean. A new module needs two entries intsconfig.frontend.json, the plain path and the?v=*form, because TypeScript allows one wildcard per pattern. -
Test code is linted and formatted along with everything else, with a few rules relaxed for
api/test,api/test-support,ui/testandtest/repoinbiome.json: a stub whose signature has to match a real one keeps its unused parameter, a scanner keepswhile ((m = re.exec(s))), and'use strict'stays where a test depends on strict-mode semantics.They are not typechecked.
checkJsoverapi/testreports 131 errors, almost all narrowing around Node'sserver.address()in test harnesses. Changing that is its own piece of work, not a side effect of something else. -
npm run lintis Biome, fromnode_modules. Run it through npm: a barenpx biomeresolves to an unrelated package that exits 0 without checking anything. A warning fails the run. Fix it or relax the rule inbiome.json; leaving it outstanding is not an option CI allows.
- Architecture: How Stackyard works
- Widgets: Build your first widget
- Translations: Translations
- Security model: Security
- Code of conduct: CODE_OF_CONDUCT.md
- Who maintains this and how decisions are made: GOVERNANCE.md