# AGENTS.md — ZDDC ## Commands ```bash # ── ./build subcommands ──────────────────────────────────────────────────── # `./build` (no arg) is a source-side dev build only — assembles tool/dist/ # + cross-compiles zddc-server. dist/release-output/ and the live site are # left alone. `./build beta` is an internal SHA snapshot for the BMC dev # chart (no public artifacts). `./build release` is the canonical stable # cut. Run `./deploy` to publish a stable cut. ./build # dev build (no release bundle) ./build beta # internal SHA snapshot for BMC dev chart # (regenerates embedded/* + chore commit; # no public artifacts in dist/release-output/) ./build release # coordinated stable cut, next version # (tags all 8 artifacts at release commit) ./build release 1.2.0 # coordinated stable cut, explicit version ./build help # ── ./deploy subcommands ──────────────────────────────────────────────────── # rsync the build output and content repo to /srv/zddc/ (Caddy's bind-mount). # --delete-after — the live tree exactly mirrors source. ./deploy # full sync (content + releases) ./deploy --content # only ~/src/zddc-website/ → /srv/zddc/ ./deploy --releases # only dist/release-output/ → /srv/zddc/releases/ # Single-tool dev build for testing (does NOT touch dist/release-output/): sh tool/build.sh # archive|transmittal|classifier|landing|form|tables|browse # Single-tool stable cut (rare; prefer ./build release so versions don't # drift between tools). sh tool/build.sh --release [] # Test all tools npm test # Test single tool npx playwright test tool # archive | transmittal | classifier | browse | form-safety | tables # Dev server (cache-busting HTTP, on port 8000) ./dev-server start ./dev-server stop ``` No lint, typecheck, or format commands exist — the project is plain sh + vanilla JS. Stable cuts seed `dist/release-output/` from the current `/srv/zddc/releases/` — copying only immutable per-version files (`_v.html`, `zddc-server_v_`) + their `.sig` sidecars + `pubkey.pem`. The cut writes this version's per-version file + canonical `.html` / `zddc-server_` symlinks on top. `./deploy --releases` (rsync `--delete-after`) cleanses any stale files in the live tree that this cut didn't include. **Nothing is pushed automatically.** Run `./deploy` to publish; commit + push source changes to `main` separately. ## Architecture Seven independent single-file HTML tools (`archive`, `transmittal`, `classifier`, `landing`, `form`, `tables`, `browse`). Each compiles to one self-contained `.html` in `dist/` with all CSS and JS inlined — most name their output `dist/tool.html`; `landing` writes `dist/index.html` (served at `/` by `zddc-server`). Tools share a small set of canonical helpers in `shared/` (filename parsing, ZDDC filter UI, theme, help) — see "Shared modules" below. `form` is the schema-driven renderer used by zddc-server's form-data system; `tables` is its read/aggregate counterpart, rendering a directory of YAML files as a sortable table whose rows click through to the form editor — discovered presence-based via `.table.yaml` next to a sibling `/` rows-dir (see "Form-data system" and "Tables system" below). `browse` is the file-tree navigator and also hosts the in-place markdown editor (`browse/js/preview-markdown.js`); the dedicated `mdedit/` tool has been retired. ``` tool/ css/ source stylesheets (concatenated in order) js/ vanilla JS IIFEs (concatenated in order) template.html placeholder markers: {{CSS_PLACEHOLDER}}, {{JS_PLACEHOLDER}}, {{BUILD_LABEL}} build.sh assembles dist/tool.html dist/tool.html generated output — committed with `git add -f` shared/ base.css CSS tokens and primitives included first by every tool's CSS build zddc.js canonical filename/folder/revision parsers, formatters, status validation zddc-filter.js shared ZDDC project/status filter UI module zddc-source.js HTTP source abstraction — FS Access API polyfill (HttpDirectoryHandle, HttpFileHandle) backed by zddc-server's listing JSON + file API (PUT/DELETE/POST). Tools that auto-load the current dir in HTTP mode call window.zddc.source.detectServerRoot() at init. The probe returns { handle, status }: status 200 → use handle; 403 → user lacks `r` on this directory (show "no permission to list" message); 0 → not http(s) or non-zddc-server. Tools must handle the 403 case so a permission-locked path doesn't silently render as an empty welcome screen. hash.js SHA-256 helpers used by the file API + classifier hashes theme.js light/dark theme switcher help.js shared help dialog module build-lib.sh POSIX sh helpers (ensure_exists, concat_files, build_timestamp) sourced by every tool's build.sh via: . "$root_dir/../shared/build-lib.sh" # Hand-edited website content lives in a SEPARATE Codeberg repo # (codeberg.org/VARASYS/ZDDC-website), typically cloned at # ~/src/zddc-website/. Just content — no releases, no LFS: # index.html, reference.html, css/, js/, img/ hand-edited content # README.md, LICENSE repo housekeeping # # This repo's ./build produces a release bundle in dist/release-output/ # (gitignored, local-only). ./deploy rsyncs both into /srv/zddc/ on # the deploy host (Caddy's bind-mount): # /srv/zddc/ # index.html, reference.html, css/, js/, img/ ← from ~/src/zddc-website # releases/ # index.html regenerated by `./build` # _v.html per-version (immutable) # _v.html -> ... symlink chain # .html -> ... canonical symlink → current stable # zddc-server_v_ per-platform binary (raw bytes, no LFS) # zddc-server_ canonical per-platform symlink → current stable # zddc-server_.html stub page surfacing 4 platform DLs helm/ zddc-server-prod/ production-shaped Helm chart (compiles from source via init container) zddc-server-dev/ dev-shaped variant (tracks main HEAD; debug-level logging; faster probes) README.md chart design rationale + quick-start ``` **Critical:** `dist/` files are gitignored. `tool/dist/.html` is the canonical built artifact for testing and the source for `--release` writes into `dist/release-output/`. `dist/release-output/` is the local-only release bundle. Neither is in git. Never edit them directly. **Two-repo + deploy-host model.** Source code lives here (`codeberg.org/VARASYS/ZDDC`); hand-edited website content lives in a separate repo (`codeberg.org/VARASYS/ZDDC-website`, typically cloned at `~/src/zddc-website/`). The live site at `zddc.varasys.io` is `/srv/zddc/` on the deploy host (Caddy bind-mount), populated by `./deploy`. Release artifacts are NOT in git — they're produced by `./build release` into `dist/release-output/` and rsync'd to `/srv/zddc/releases/` by `./deploy --releases`. Each tool has exactly one canonical URL (`.html`, symlink → current stable) and a set of per-version immutable files (`_v.html`). Same shape for zddc-server per platform. `shared/build-lib.sh` provides `promote_release` (HTML tools) and `promote_zddc_server` (binaries + matching stub pages); the top-level `./build` seeds per-version immutables from live state, then calls them in lockstep. Older releases are reproducible from any `-vX.Y.Z` tag in this repo (`git checkout zddc-server-v0.0.8 && ./build release 0.0.8`). No Codeberg release assets, no LFS. ## Shared CSS (`shared/base.css`) Included as the **first** positional arg to every tool's `concat_files` CSS call. Provides: - `:root` CSS custom properties — `--primary`, `--bg`, `--text`, `--border`, `--font`, etc. - Brand color: `--primary: #2a5a8a` (matches zddc.varasys.io) - Button primitive: `.btn`, `.btn-primary`, `.btn-secondary`, `.btn-sm`, `.btn-lg`, `.btn-link` - `.app-header` + `.app-header__title` chrome rules - `.build-timestamp`, `.hidden`, `.truncate`, webkit scrollbars **Do not** define these in any tool's own CSS — they come from shared. **Toast CSS** lives in `classifier/css/base.css` only (classifier is the only tool that uses toasts). ## Transmittal CSS quirks - `transmittal/css/base.css` overrides `html { font-size: 16px }` inside `@media screen` — this must stay. `shared/base.css` sets `14px`; transmittal's floating labels are rem-based and were designed for 16px. - The floating label position is defined in `transmittal/css/forms.css`, not Tailwind classes. If adding new Tailwind classes to `template.html`, add them to `transmittal/css/utilities.css` too — there is no Tailwind build step. ## Build system rules - Every `build.sh` sources `shared/build-lib.sh` first (provides `ensure_exists`, `concat_files`, `build_timestamp`). Set `root_dir` before sourcing. - Build scripts use **POSIX sh** (`#!/bin/sh` with `set -eu`), not bash. - `concat_files` accepts **positional args only** (not array names). - `awk` processes `template.html`, replacing `{{PLACEHOLDER}}` markers and stripping CDN `