ZDDC/build.sh
ZDDC 91d6e61e22 feat(web): releases index, alpha+beta channel builds, inline server section
Three things on the public website:

1) Cut alpha and beta channel builds for all five tools, so each tool
   now has stable + beta + alpha actually published — previously
   beta and alpha were vapor for archive (which had been freshened
   earlier) and missing entirely for the others. The intro page's
   tool cards now point at real artifacts on every channel.

2) New website/releases/index.html — a generated index of every
   version + channel of every tool, with stable/beta/alpha pill
   links per tool and a "Pin to version" row of every concrete
   v0.0.X build. Regenerated by build.sh's new build_releases_index
   function (reads the filesystem so it is always consistent with
   what is actually under releases/). Linked from the intro page nav
   (Releases), from the bottom of the Try the tools section
   ("Browse all versions"), and from the Learn more list.
   reference.html's nav gets the same Releases link.

3) Folded website/zddc-server.html into website/index.html as a new
   inline section ("zddc-server (optional)") below the tool cards.
   The earlier separate page is removed; the broken Server nav link
   that pointed at it is gone too. The new section leads with the
   dual-mode insight (the tools work locally on a folder OR via any
   web server, including the optional zddc-server) and frames
   zddc-server as a small Go binary that adds things a generic web
   server cannot: ACL via .zddc files, virtual .archive URL space,
   per-request access logging, mundane glue. The What is it?
   paragraph also mentions the dual-mode story up front so users
   reading top-to-bottom get the framing before they hit the cards.

Also caught two stale _latest.html refs missed by the earlier
rename sweep: 8 tool links in reference.html and a comment line in
CLAUDE.md. Verified with a full link audit — every relative href in
index.html, reference.html, and releases/index.html now resolves to
an existing file under website/.

ARCHITECTURE.md doc-ownership table updated: zddc-server.html row
removed; new row added for the regenerated releases/index.html.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 10:00:10 -05:00

260 lines
11 KiB
Bash
Executable file

#!/bin/sh
set -eu
# Top-level build script — builds all ZDDC HTML tools, the zddc-server
# binaries, and the downloadable bundles (install.zip and track-*.zip).
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
echo "=== Building ZDDC tools ==="
sh "$SCRIPT_DIR/transmittal/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/archive/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/classifier/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/mdedit/build.sh" "${1:-}" "${2:-}"
sh "$SCRIPT_DIR/landing/build.sh" "${1:-}" "${2:-}"
echo ""
echo "=== Assembling zddc/dist/web/ ==="
# Only landing and archive ship inside the server bundle: they call the
# server's JSON API (GET / for the project list, directory listings for the
# archive) and are useless without it. transmittal, classifier, and mdedit
# are pure client-side tools that work from file:// or any static host;
# they are released to website/ for download but not bundled with the server.
mkdir -p "$SCRIPT_DIR/zddc/dist/web"
cp "$SCRIPT_DIR/landing/dist/index.html" "$SCRIPT_DIR/zddc/dist/web/index.html"
cp "$SCRIPT_DIR/archive/dist/archive.html" "$SCRIPT_DIR/zddc/dist/web/archive.html"
echo "Wrote zddc/dist/web/index.html"
echo "Wrote zddc/dist/web/archive.html"
# Cross-compiled zddc-server binaries are built via podman if available
# (no-op otherwise — CI builds the runtime container directly via the
# Containerfile's builder stage and doesn't need host-side binaries).
echo ""
echo "=== Building zddc-server binaries ==="
if command -v podman >/dev/null 2>&1; then
podman build --target binaries -o "$SCRIPT_DIR/zddc/dist/" "$SCRIPT_DIR/zddc/" 2>&1 | grep -v "^-->"
else
echo "podman not found — skipping cross-compiled binary build."
echo " (CI builds the container image directly; this step only matters"
echo " for releasing the standalone Linux/macOS/Windows binaries.)"
fi
# ─── Bootstrap zips ──────────────────────────────────────────────────────────
# Generated from bootstrap/level{1,2}.html.tmpl on every build so they are
# always in sync with the current bootstrap pattern.
#
# install.zip — drop into deployment root for self-contained install.
# Contains the 5 current-stable HTMLs at root plus a
# _template/ directory with 4 level-1 stubs that
# projects can use as their starting layout.
# track-<channel>.zip — drop the level-2 stubs over deployment root to make
# the whole site track <channel> from zddc.varasys.io.
#
# install.zip needs at least one stable release to exist under
# website/releases/; if none exist yet, that zip is skipped with a warning.
WEBSITE_DIR="$SCRIPT_DIR/website"
RELEASES_DIR="$WEBSITE_DIR/releases"
BOOTSTRAP_DIR="$SCRIPT_DIR/bootstrap"
mkdir -p "$WEBSITE_DIR"
# tool|filename|title
TOOL_TABLE='archive|archive.html|Archive
transmittal|transmittal.html|Transmittal
classifier|classifier.html|Classifier
mdedit|mdedit.html|Markdown Editor
landing|index.html|ZDDC'
# Substitute {{TOOL}}, {{TOOL_TITLE}}, {{CHANNEL}} in a template.
# Substitute {{TOOL}}, {{TOOL_TITLE}}, {{CHANNEL}} in a template.
render_stub() {
sed \
-e "s|{{TOOL_TITLE}}|$3|g" \
-e "s|{{TOOL}}|$2|g" \
-e "s|{{CHANNEL}}|${4:-}|g" \
"$1" > "$5"
}
build_install_zip() {
# Verify a stable release exists for every tool before staging.
_missing=""
while IFS='|' read -r _tool _file _title; do
[ -e "$RELEASES_DIR/${_tool}_stable.html" ] || _missing="$_missing $_tool"
done <<EOF
$TOOL_TABLE
EOF
if [ -n "$_missing" ]; then
echo "Skipping install.zip — no stable release for:$_missing"
return 0
fi
_staging=$(mktemp -d)
while IFS='|' read -r _tool _file _title; do
cp "$RELEASES_DIR/${_tool}_stable.html" "$_staging/$_file"
done <<EOF
$TOOL_TABLE
EOF
# _template/ holds level-1 bootstraps for the four interactive tools
# (landing only lives at deployment root; project directories do not
# have their own landing page).
mkdir -p "$_staging/_template"
while IFS='|' read -r _tool _file _title; do
render_stub "$BOOTSTRAP_DIR/level1.html.tmpl" "$_tool" "$_title" "" "$_staging/_template/$_file"
done <<EOF
archive|archive.html|Archive
transmittal|transmittal.html|Transmittal
classifier|classifier.html|Classifier
mdedit|mdedit.html|Markdown Editor
EOF
cp "$BOOTSTRAP_DIR/README.md" "$_staging/README.md"
rm -f "$WEBSITE_DIR/install.zip"
(cd "$_staging" && zip -qr "$WEBSITE_DIR/install.zip" .)
echo "Wrote $WEBSITE_DIR/install.zip"
rm -rf "$_staging"
}
build_track_zip() {
_channel="$1"
_staging=$(mktemp -d)
while IFS='|' read -r _tool _file _title; do
render_stub "$BOOTSTRAP_DIR/level2.html.tmpl" "$_tool" "$_title" "$_channel" "$_staging/$_file"
done <<EOF
$TOOL_TABLE
EOF
rm -f "$WEBSITE_DIR/track-$_channel.zip"
(cd "$_staging" && zip -qr "$WEBSITE_DIR/track-$_channel.zip" .)
echo "Wrote $WEBSITE_DIR/track-$_channel.zip"
rm -rf "$_staging"
}
# Regenerate website/releases/index.html — a static directory listing of
# all tool releases with channel rows + per-version archive links. Read
# from the filesystem so the page is always consistent with what's there.
build_releases_index() {
_out="$RELEASES_DIR/index.html"
{
cat <<'HEAD'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Releases — ZDDC</title>
<meta name="description" content="All released versions and channel builds of every ZDDC tool.">
<meta name="theme-color" content="#2a5a8a">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/style.css">
<style>
.rel-tool { margin-top: var(--spacing-xl); padding: var(--spacing-md); border: 1px solid var(--color-border); border-radius: 8px; }
.rel-tool h2 { margin-top: 0; }
.rel-channels { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 1.25rem 0; }
.rel-channels a { padding: 0.25rem 0.625rem; border-radius: 999px; text-decoration: none; border: 1px solid var(--color-border); color: var(--color-text); font-size: 0.9rem; }
.rel-channels a.stable { border-color: var(--color-primary); color: var(--color-primary); font-weight: 600; }
.rel-channels a.beta, .rel-channels a.alpha { color: var(--color-text-muted); }
.rel-channels a:hover { background: var(--color-bg-subtle); }
.rel-versions { font-size: 0.875rem; color: var(--color-text-muted); }
.rel-versions a { margin-right: 0.5rem; color: var(--color-text); text-decoration: none; padding: 0.1rem 0.4rem; border-radius: 4px; }
.rel-versions a:hover { background: var(--color-bg-subtle); text-decoration: underline; }
.rel-meta { font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.5rem; }
</style>
</head>
<body>
<header class="site-header">
<div class="container header-content">
<a href="/" class="brand">
<div class="brand-logo">
<svg viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h6v2H3v-2z" /></svg>
</div>
<span class="brand-name">ZDDC</span>
</a>
<nav class="header-nav">
<a href="/" class="nav-link">Home</a>
<a href="../reference.html" class="nav-link">Docs</a>
<a href="index.html" class="nav-link active">Releases</a>
</nav>
</div>
</header>
<section class="hero">
<div class="container">
<h1>Releases</h1>
<p class="hero-subtitle">All published versions and channel builds of every ZDDC tool. Stable releases are immutable; alpha and beta channels are rebuilt without notice.</p>
</div>
</section>
<main class="container" style="margin-bottom: var(--spacing-2xl);">
HEAD
printf '%s\n' "$TOOL_TABLE" | while IFS='|' read -r _tool _file _title; do
_stable_target=""
if [ -L "$RELEASES_DIR/${_tool}_stable.html" ]; then
_stable_target=$(readlink "$RELEASES_DIR/${_tool}_stable.html")
fi
printf ' <section class="rel-tool">\n'
printf ' <h2>%s</h2>\n' "$_title"
printf ' <div class="rel-channels">\n'
[ -e "$RELEASES_DIR/${_tool}_stable.html" ] && printf ' <a class="stable" href="%s_stable.html">stable</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_beta.html" ] && printf ' <a class="beta" href="%s_beta.html">beta</a>\n' "$_tool"
[ -e "$RELEASES_DIR/${_tool}_alpha.html" ] && printf ' <a class="alpha" href="%s_alpha.html">alpha</a>\n' "$_tool"
printf ' </div>\n'
_versions=$(ls -1 "$RELEASES_DIR" 2>/dev/null | grep -E "^${_tool}_v[0-9]" | sort -V -r)
if [ -n "$_versions" ]; then
printf ' <div class="rel-versions"><strong>Pin to version:</strong>\n'
printf '%s\n' "$_versions" | while read -r _v; do
_ver=${_v#${_tool}_v}; _ver=${_ver%.html}
printf ' <a href="%s">v%s</a>\n' "$_v" "$_ver"
done
printf ' </div>\n'
fi
if [ -n "$_stable_target" ]; then
printf ' <div class="rel-meta">stable currently → %s</div>\n' "$_stable_target"
fi
printf ' </section>\n'
done
cat <<'TAIL'
<section style="margin-top: var(--spacing-2xl); color: var(--color-text-muted); font-size: 0.9rem;">
<p>Append <code>?v=alpha</code>, <code>?v=beta</code>, <code>?v=stable</code>, or <code>?v=0.0.1</code> to any deployment URL to switch versions for a single request — see <a href="../">the home page</a>.</p>
</section>
</main>
<footer class="site-footer">
<div class="container footer-content">
<span>ZDDC is open source — <a href="https://codeberg.org/VARASYS/ZDDC">codeberg.org/VARASYS/ZDDC</a></span>
</div>
</footer>
</body>
</html>
TAIL
} > "$_out"
echo "Wrote $_out"
}
echo ""
echo "=== Building install.zip, track-*.zip, releases/index.html ==="
build_install_zip
build_track_zip alpha
build_track_zip beta
build_track_zip stable
build_releases_index
echo ""
echo "=== All tools built successfully ==="
echo ""
echo "Server deployment package: zddc/dist/"
echo " Binaries: zddc-server-{linux,darwin,windows}-*"
echo " Web files: web/ (copy contents to ZDDC_ROOT)"
echo ""
echo "Bootstrap downloads: website/"
echo " install.zip — self-contained install for deployment root"
echo " track-alpha.zip — level-2 stubs that track the alpha channel"
echo " track-beta.zip — level-2 stubs that track the beta channel"
echo " track-stable.zip — level-2 stubs that track the stable channel"