ZDDC/bootstrap
ZDDC 2dc9ad240c refactor: distribute via Codeberg release assets, drop the upstream image
Removes the codeberg.org/varasys/zddc-server registry image, which had
no remaining consumer outside this shop. The two chart Dockerfiles
(tnd-zddc-chart) now compile zddc-server from source at build time,
fetching the right tag from a Codeberg release. release-image.sh,
zddc/Containerfile, and zddc/podman-compose.yaml are gone.

Build artifacts (HTML tools + zddc-server binaries) move from
website/releases/ in this repo to Codeberg release assets attached to
git tags. The website at zddc.varasys.io serves them by reverse-
proxying /releases/<tag>/<asset> to the corresponding Codeberg URL,
so consumers (zddc-use, level-2 bootstrap stubs, the chart
Dockerfiles) only ever talk to zddc.varasys.io.

Releases page becomes server-rendered static HTML regenerated on each
build via a single Codeberg API call. A small website/releases/manifest.json
maps <tool>-<channel> → tag for runtime channel resolution by zddc-use
and the level-2 stubs.

Files added:
- shared/publish-codeberg-release.sh — POSIX-sh helper that creates a
  Codeberg release for a tag (sets prerelease flag from tag suffix)
  and uploads/replaces release assets idempotently. Sourced by
  build-lib.sh and zddc/release.sh.
- zddc/release.sh — replaces release-image.sh. Tags + cross-compiles
  binaries via native Go (no podman needed; install Go) + uploads to
  Codeberg release assets. No image build, no registry push.

Files modified:
- shared/build-lib.sh — promote_release tags + uploads via the helper
  for stable AND alpha/beta now (alpha/beta were untagged before).
  update_alpha removed; per-tool build.sh files no longer mirror to
  website/releases/<tool>_alpha.html on plain dev builds.
- build.sh — prefers native go build over the old podman-based
  cross-compile (which is gone with Containerfile). build_releases_index
  queries the Codeberg API once and writes static HTML + manifest.json,
  with graceful fallback when the API is unreachable.
- bootstrap/level2.html.tmpl — fetches manifest.json to resolve
  channel → tag, then fetches the asset from /releases/<tag>/<asset>
  (Caddy proxy). Replaces the old /releases/<tool>_<channel>.html flat
  URL pattern. Operators with curl'd level-2 stubs need to re-issue
  them — this is a breaking change.
- AGENTS.md, CLAUDE.md — rewritten to describe the new flow.
- .gitignore — releases/ artifacts now expected to be on Codeberg, not
  committed locally.

NOT in this commit (deferred until $CODEBERG_TOKEN is provisioned):
- Backfilling existing tags as Codeberg releases.
- Cleanup commit: git rm-ing the existing artifacts in website/releases/.
  Until backfill happens, those files are how operators with old
  bootstrap stubs still get content. Once Codeberg has the assets,
  drop them.
- The Caddy reverse-proxy config on zddc.varasys.io.

Operator-side changes (not in this repo):
- tnd-zddc-chart Dockerfile.prod and Dockerfile (dev) need updating
  to compile from source rather than `FROM codeberg.org/...:stable`.
  Done in a separate commit on that repo.
- Caddyfile rule for the /releases/<tag>/<asset> reverse-proxy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:18:26 -05:00
..
level1.html.tmpl feat(tools,build): in-flight HTML-tool reworks and build-infra updates 2026-04-29 12:52:27 -05:00
level2.html.tmpl refactor: distribute via Codeberg release assets, drop the upstream image 2026-04-29 21:18:26 -05:00
README.md feat(install): replace .zip downloads with copy-paste shell snippets 2026-04-29 13:30:32 -05:00

Deployment bootstrap

ZDDC tools (archive, transmittal, classifier, mdedit, landing) are single-file HTML bundles. The bootstrap pattern lets you install once on a deployment and update by editing a few lines, without re-uploading multi-megabyte HTML files.

End users install via a short copy-paste shell snippet from the home page's "Install on your server" section. The snippet uses curl to fetch either the current stable HTMLs (self-contained) or tiny level-2 stubs (channel trackers) into the deployment directory. The published stubs live under https://zddc.varasys.io/bootstrap/:

  • bootstrap/level1/<tool>.html — same-origin level-1 stubs (4 tools, no landing — landing only lives at deployment root).
  • bootstrap/track-{stable,beta,alpha}/<tool>.html — per-channel level-2 stubs (5 tools each).

Both directories are produced by the project's top-level build.sh from bootstrap/level{1,2}.html.tmpl.

The two-level model

A typical zddc-server deployment looks like this:

<ZDDC_ROOT>/
  index.html                # landing tool (or bootstrap)
  archive.html              # archive tool (or bootstrap; site-wide channel switch lives here)
  transmittal.html
  classifier.html
  mdedit.html
  <project-A>/
    archive.html            # level-1 bootstrap → fetches ../archive.html
    transmittal.html
    classifier.html
    mdedit.html
    <project files…>
  <project-B>/
    archive.html            # level-1 bootstrap (or pinned to a specific version)
    …
  • Level-1 stubs at <project>/<tool>.html always fetch the same-origin ../<tool>.html. They never touch zddc.varasys.io. Install them once; they don't need to change.
  • At deployment root (<ZDDC_ROOT>/<tool>.html), put either:
    • the actual built tool HTML — fully self-contained install, no external dependencies; or
    • a level-2 bootstrap — fetches a specific channel or pinned version from https://zddc.varasys.io/releases/<tool>_<channel|v…>.html.

The site administrator switches the whole site to a channel by re-running the track-<channel> install snippet from the home page — that overwrites the root <tool>.html files with the matching level-2 stubs. A single project can override one tool by editing just <project-X>/<tool>.html (replace the relative upstream URL with an absolute zddc.varasys.io URL).

Why two levels

The level-1 stubs let projects share a single source of truth for "which build of the archive tool runs here." Switching channels is one file change at the root; pinning a single project is one file change in that directory.

document.write() chains across both levels: level-1 fetches and writes, the new document's level-2 script runs and writes again, the third write is the actual tool. Origin stays at the deployment domain throughout, so File System Access API, crypto.subtle, and localStorage all work and preferences stay scoped to the deployment.

Pinning options

There are two ways to choose a version: edit the stub for a permanent pin, or pass a ?v= URL parameter for a per-request override.

1. Permanent pin (edit the stub)

Each stub has one fallback/upstream constant. Edit it once and the choice sticks for everyone using that file.

URL Behavior
https://zddc.varasys.io/releases/<tool>_stable.html current stable; auto-updates within stable
https://zddc.varasys.io/releases/<tool>_beta.html latest beta build (mutable)
https://zddc.varasys.io/releases/<tool>_alpha.html latest alpha build (mutable)
https://zddc.varasys.io/releases/<tool>_v1.2.3.html pinned to exact stable version

2. Per-request ?v= parameter

Both stub levels honor a ?v= URL parameter. The parameter survives the document.write() chain, so it flows through level-1 → level-2 → upstream automatically.

URL parameter Behavior
?v=0.0.4 (or ?v=v0.0.4) tries <tool>_v0.0.4.html locally, then upstream
?v=alpha switches to alpha channel
?v=beta switches to beta channel
?v=latest latest stable
(omitted) the default baked into the stub

When level-1 has ?v=…, it tries ../<tool>_<suffix>.html first (useful when the admin has staged specific versions locally) and falls back to ../<tool>.html if 404 — which then forwards the parameter via level-2 if one is installed. So the same URL works whether the version is staged locally, served by a level-2 stub, or both.

Stable releases are immutable. Alpha and beta channel files are overwritten in place each time their channel is rebuilt; expect them to change without notice. The build label rendered on the tool page tells you what you are running (date + commit SHA for alpha/beta, version number for stable).

Auditing what's installed

Every stub contains a fallback (level-1) or upstream (level-2) constant. To see what each tool / project on the deployment points at:

grep -rn "fallback\|upstream" <ZDDC_ROOT>

CORS prerequisite (level-2 only)

A level-2 fetch is cross-origin (deployment → zddc.varasys.io). The upstream must serve Access-Control-Allow-Origin: * (or a list including your deployment origin) on the released HTML files. Verify with:

curl -I https://zddc.varasys.io/releases/archive_stable.html | grep -i access-control

Level-1 fetches are same-origin so no CORS is involved.

Templates

level1.html.tmpl and level2.html.tmpl are the source of truth. The project's top-level build.sh substitutes {{TOOL}}, {{TOOL_TITLE}}, {{CHANNEL}}, and {{FAVICON}} to produce the per-tool stubs published under website/bootstrap/level1/ and website/bootstrap/track-<channel>/, which the install snippets curl from https://zddc.varasys.io/bootstrap/.