Development
This page is generated from CONTRIBUTING.md in the Stackyard repository, so it matches the source. Links in it resolve to files on GitHub.
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.
Development
The frontend is static; edit files under ui/ and reload. 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.
Before opening a PR
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 it:
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
npm run lint
npm run format:check
npm run typecheck
npm run typecheck:ui
docker build -t stackyard:ci .
CodeQL also runs on every pull request. A finding it reports has to be resolved before merge.
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 in docs/releasing.md.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-supportandui/testinbiome.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.
More
- Frontend layout: docs/frontend.md
- Widgets: docs/widgets.md
- Translations: docs/i18n.md
- Security model / reporting: docs/security.md
- Code of conduct: CODE_OF_CONDUCT.md
Reference
Deeper notes in the repository, beyond the ones linked above.
| Document | Covers |
|---|---|
| Architecture | How a request is served, and where config lives. |
| Design system | Colour, type, geometry and motion. |
| API errors | The error shape the API returns, and what each code means. |
| Releasing | How a version is cut and published. |