Files
klarbild-oss/CONTRIBUTING.md
T
tillandClaude Opus 5 e2481139a1
CI / check (push) Has been cancelled
Klarbild 1.0.0 — first public release
A self-hosted print studio: images at exact physical sizes, sheet layout with
crop marks, tiling, 1:1 PDF. Everything else — image generation, delivery,
share links, mail, Telegram — is an optional module that is off by default.

This is the neutral public twin of a private tool. Compared to that original:

- optional modules behind KLARBILD_MODULES; the default install is print-only
- English interface with German as a full second language (1,038 strings);
  the English sentence is the translation key
- no built-in accounts — first boot creates one admin from ADMIN_USERNAME /
  ADMIN_PASSWORD, or generates a password and logs it once
- delivery and backup targets are generic SFTP/FTPS endpoints, off by default
- English routes, English identifiers, English comments throughout
- two compose files: print-only by default, everything in the full one
- AGPL-3.0, CI (build, tests, type check, secret scan), CONTRIBUTING, SECURITY

124 tests green, type check clean, verified end to end against a live instance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
2026-09-15 14:52:41 +00:00

3.0 KiB

Contributing

Thanks for looking. Klarbild is a small project with one maintainer, so the most useful contributions are the ones that arrive ready to merge: a clear problem, a minimal change, and a test where a test is possible.

Getting it running

npm install
cp .env.example .env     # DATABASE_URL, SESSION_SECRET, ENCRYPTION_KEY
npm run dev

You need a PostgreSQL to point DATABASE_URL at; docker compose up db gives you one. Migrations run themselves on the first request.

npm test          # 124 tests, no database needed
npx tsc --noEmit  # must be clean
npm run build

Both npm test and tsc run in CI and both must be green.

How the code is laid out

src/lib/print*.ts     the print engine — pure arithmetic, heavily tested
src/lib/paper.ts      86 image sizes, 19 paper formats, the size parser
src/lib/modules.ts    which optional modules are switched on
src/lib/i18n.ts       translation; the English sentence is the key
src/components/       React islands, one per screen
src/pages/            Astro pages and the API under src/pages/api/
migrations/           numbered SQL, forward-only, idempotent, run on boot
tests/                node:test, no framework

The rule that matters most: the browser preview and the server-side PDF use the same layout code. If you change how a sheet is laid out, change it in src/lib/printlayout.ts and both follow. Anything that recomputes geometry in a component is a bug waiting to happen.

House style

  • Comments explain why, and carry the number that justifies the decision. "Measured: 440 MB of images peaked at 196 MB of memory" is worth more than "stream the files". Please keep that habit; it is most of what makes this codebase navigable.
  • No new dependency without a reason in the pull request. There are 20 runtime dependencies and that is already plenty.
  • Two-space indent, no semicolon crusade, no reformatting of files you did not otherwise touch.
  • Metric units. English decimal point in English strings.

Translation

The English string in the source is the key. To add a language:

  1. Copy src/locales/de.json to src/locales/<code>.json and translate the values.
  2. Add the code to LOCALES and LOCALE_NAMES in src/lib/i18n.ts, and to DICTS in src/lib/i18n.server.ts.

A missing key falls back to English, so a partial translation is still useful. Never build a sentence by concatenation — use a named placeholder: t('{done} of {total} done', { done, total }).

Adding a module

Optional features live behind src/lib/modules.ts. A new one needs: an entry in MODULE_IDS and MODULE_INFO, a has('yours') guard on its navigation entry and its settings card, and if (!has('yours')) return moduleOff('yours') at the top of every API route it owns. The test is simple — with the module off, the instance should not hint that the feature exists.

Pull requests

One change per pull request. Say what breaks if it is wrong. If you found a bug you are not fixing, an issue with a reproduction is genuinely useful on its own.