Restructures the version picker on the releases page so channel
mirrors are first-class, selectable options:
Channels (mutable URLs)
stable — currently v0.0.8 ← default selection
beta — tracks stable
alpha — tracks stable
Pinned versions (immutable URLs)
v0.0.8
v0.0.2
v0.0.1
Picking "stable" now rewires every download link on the page to the
*_stable.html (HTML tools) or zddc-server_stable_<plat> (binary)
channel-mirror URL — the kind a user wants to copy + bookmark for a
"latest stable" reference. Same for beta and alpha. Picking a pinned
vX.Y.Z still rewires to immutable per-version URLs.
Removed the separate "Or pick a channel" chip-pill row that previously
sat under the picker. The dropdown is now the single control; chips
duplicated functionality and added visual noise. The .channel-chips
CSS rules in website/css/style.css come out with them.
Static defaults (without JS) now use the stable channel mirror URLs
too, so both copy-from-source and JS-rewire produce the same outcome
for users who want stable. The page works end-to-end with JS off.
Embedded snapshots refreshed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
259 lines
14 KiB
HTML
259 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Download ZDDC</title>
|
|
<meta name="description" content="Self-host the ZDDC server, or download individual tools. Pin a version your project trusts; your archive's tools are yours.">
|
|
<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">
|
|
</head>
|
|
<body>
|
|
<header class="site-header">
|
|
<div class="container header-content">
|
|
<a href="/" class="brand">
|
|
<svg class="brand-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" aria-hidden="true">
|
|
<rect width="64" height="64" rx="12" fill="#1e3a5f"/>
|
|
<g fill="#fff">
|
|
<rect x="14" y="18" width="36" height="7"/>
|
|
<polygon points="43,25 50,25 21,43 14,43"/>
|
|
<rect x="14" y="43" width="36" height="7"/>
|
|
</g>
|
|
</svg>
|
|
<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">Download</a>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="hero">
|
|
<div class="container">
|
|
<h1>Download ZDDC</h1>
|
|
<p class="hero-subtitle">Pick how you want to use it. Pick the version you want. Every link below points at a real, immutable file you can save into your archive — your tools, your version, forever.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<main class="container" style="margin-bottom: var(--spacing-2xl);">
|
|
<div class="version-picker-bar">
|
|
<label for="version-picker">Showing</label>
|
|
<select id="version-picker">
|
|
<optgroup label="Channels (mutable URLs)">
|
|
<option value="stable" selected>stable — currently v0.0.8</option>
|
|
<option value="beta">beta — tracks stable</option>
|
|
<option value="alpha">alpha — tracks stable</option>
|
|
</optgroup>
|
|
<optgroup label="Pinned versions (immutable URLs)">
|
|
<option value="v0.0.8">v0.0.8</option>
|
|
<option value="v0.0.2">v0.0.2</option>
|
|
<option value="v0.0.1">v0.0.1</option>
|
|
</optgroup>
|
|
</select>
|
|
<span class="picker-hint">Changes every download link below.</span>
|
|
</div>
|
|
|
|
<!-- ───────────── Path A — Self-host the server ───────────── -->
|
|
<section class="card" style="background: var(--color-bg-subtle); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--spacing-lg) var(--spacing-xl); margin-top: var(--spacing-lg);">
|
|
<h2 style="margin-top:0;">Path A — Self-host the server</h2>
|
|
<p>One small Go binary. <strong>All five tools are baked in</strong> via <code>//go:embed</code>; the server picks the right one for each folder of your archive. Adds ACL via <code>.zddc</code> files, the virtual <code>.archive</code> document index, and SSO header passthrough. Stop the server and the directory is still a perfectly valid ZDDC archive — the server is convenience, not lock-in.</p>
|
|
<a class="dl-primary"
|
|
data-tool="zddc-server"
|
|
data-platform="linux-amd64"
|
|
href="zddc-server_stable_linux-amd64"
|
|
id="dl-primary-binary">
|
|
<span class="dl-icon">⬇</span>
|
|
<span>Download <span id="dl-primary-platlabel">for Linux (x86_64)</span></span>
|
|
</a>
|
|
<span class="dl-primary-meta" id="dl-primary-meta">zddc-server_stable_linux-amd64</span>
|
|
<div class="dl-secondary-row" id="dl-others">
|
|
<span>Other platforms:</span>
|
|
<a data-tool="zddc-server" data-platform="linux-amd64" href="zddc-server_stable_linux-amd64">Linux (x86_64)</a>
|
|
<a data-tool="zddc-server" data-platform="darwin-amd64" href="zddc-server_stable_darwin-amd64">macOS (Intel)</a>
|
|
<a data-tool="zddc-server" data-platform="darwin-arm64" href="zddc-server_stable_darwin-arm64">macOS (Apple Silicon)</a>
|
|
<a data-tool="zddc-server" data-platform="windows-amd64" href="zddc-server_stable_windows-amd64.exe">Windows (x86_64)</a>
|
|
</div>
|
|
<p style="margin-top: var(--spacing-md); font-size: 0.92rem; color: var(--color-text-muted);">
|
|
After download: <code>chmod +x</code> the file, set <code>ZDDC_ROOT=/path/to/archive</code>, run.
|
|
Need a different platform? <a href="https://codeberg.org/VARASYS/ZDDC">Build from source</a> at the matching tag.
|
|
</p>
|
|
</section>
|
|
|
|
<!-- ───────────── Path B — Standalone tool HTMLs ───────────── -->
|
|
<section class="card" style="border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--spacing-lg) var(--spacing-xl); margin-top: var(--spacing-xl);">
|
|
<h2 style="margin-top:0;">Path B — Standalone tools</h2>
|
|
<p>Every tool is a single self-contained HTML file. <strong>Open it locally and point it at a folder on your disk</strong> — no install, no server, no account. Same on-disk layout the server uses. Use one tool, use all five, mix and match — there is no orchestration to set up.</p>
|
|
<div class="grid-4" style="margin-top: var(--spacing-md);">
|
|
<a class="tool-card" data-tool="archive" href="archive_stable.html">
|
|
<span class="tool-card__title">Archive Browser</span>
|
|
<span class="tool-card__desc">Browse and download from a ZDDC archive.</span>
|
|
<span class="tool-card__link">Download →</span>
|
|
</a>
|
|
<a class="tool-card" data-tool="transmittal" href="transmittal_stable.html">
|
|
<span class="tool-card__title">Transmittal Creator</span>
|
|
<span class="tool-card__desc">Build, sign, and verify transmittal packages.</span>
|
|
<span class="tool-card__link">Download →</span>
|
|
</a>
|
|
<a class="tool-card" data-tool="classifier" href="classifier_stable.html">
|
|
<span class="tool-card__title">Classifier</span>
|
|
<span class="tool-card__desc">Rename loose files to ZDDC convention.</span>
|
|
<span class="tool-card__link">Download →</span>
|
|
</a>
|
|
<a class="tool-card" data-tool="mdedit" href="mdedit_stable.html">
|
|
<span class="tool-card__title">Markdown Editor</span>
|
|
<span class="tool-card__desc">Edit project markdown files in place.</span>
|
|
<span class="tool-card__link">Download →</span>
|
|
</a>
|
|
<a class="tool-card" data-tool="landing" href="landing_stable.html">
|
|
<span class="tool-card__title">Landing</span>
|
|
<span class="tool-card__desc">Project picker for multi-project servers.</span>
|
|
<span class="tool-card__link">Download →</span>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ───────────── Pinning empowerment narrative ───────────── -->
|
|
<section class="card" style="border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--spacing-lg) var(--spacing-xl); margin-top: var(--spacing-xl);">
|
|
<h2 style="margin-top:0;">Your version, forever</h2>
|
|
<p>Your server may run v0.0.8 next month and v0.1.0 the month after. <strong>Your project doesn't have to follow.</strong> If you depend on a specific behavior in <code>archive</code> v0.0.5, save that version into your archive — the next server upgrade can't take it away from you. Two ways to do it:</p>
|
|
<div class="grid-2" style="margin-top: var(--spacing-md);">
|
|
<div class="pin-card">
|
|
<h3>Drop a copy into your archive</h3>
|
|
<p>Save the tool's HTML at the path the server would serve it from. The server's resolution order picks up real files <em>first</em> — before any cascade or embedded fallback.</p>
|
|
<pre>curl -o MyProject/archive.html \
|
|
https://zddc.varasys.io/releases/archive_v0.0.8.html</pre>
|
|
<p>Now <code>MyProject/archive.html</code> is yours. The server serves your bytes; nothing about a future <code>--release</code> can change them.</p>
|
|
</div>
|
|
<div class="pin-card">
|
|
<h3>Pin via <code>.zddc</code></h3>
|
|
<p>Less invasive — no copies in your archive, just a small config entry telling the server which version to fetch and cache. Closer-to-leaf wins, so subprojects can pin further.</p>
|
|
<pre># MyProject/.zddc
|
|
apps:
|
|
archive: v0.0.8</pre>
|
|
<p>Server fetches once on first hit, caches under <code>_app/</code>, falls through to the embedded copy if the fetch fails.</p>
|
|
</div>
|
|
</div>
|
|
<p class="pin-note">Your archive's tools are <strong>yours</strong>. The server is convenience; deletion of the server doesn't break your archive — every per-version download above is a real, immutable static file. Save what you trust.</p>
|
|
</section>
|
|
|
|
<!-- ───────────── Channels explainer ───────────── -->
|
|
<section class="card" style="border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--spacing-lg) var(--spacing-xl); margin-top: var(--spacing-xl); margin-bottom: var(--spacing-xl);">
|
|
<h2 style="margin-top:0;">Channels</h2>
|
|
<p>Three channels, applied in lockstep across all tools. Pre-release channels exist to soak changes; <strong>stable</strong> is what production runs.</p>
|
|
<div class="channel-explainer">
|
|
<div>
|
|
<h4 class="alpha">alpha</h4>
|
|
<p>Active dev iteration. Rebuilds without notice. Look here for the very latest.</p>
|
|
</div>
|
|
<div>
|
|
<h4 class="beta">beta</h4>
|
|
<p>Ready for general testing. Has soaked through alpha. Still mutable — pin to a versioned URL for reproducibility.</p>
|
|
</div>
|
|
<div>
|
|
<h4 class="stable">stable</h4>
|
|
<p>Ready to ship. Every per-version file is immutable; <code>_stable</code> follows the latest cut. Channel cuts cascade: stable cut resets beta and alpha to track stable.</p>
|
|
</div>
|
|
</div>
|
|
</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>
|
|
|
|
<script>
|
|
(function() {
|
|
// Platform auto-detect: choose the most likely binary for this user's
|
|
// OS on first paint. Promotes that platform to the primary CTA; the
|
|
// other three render in the secondary row. UA-sniffing is good
|
|
// enough — wrong guesses fall through to the always-visible
|
|
// "Other platforms" row below.
|
|
var ua = navigator.userAgent || '';
|
|
var detected = 'linux-amd64'; // sensible default
|
|
var platLabel = 'Linux (x86_64)';
|
|
if (/Macintosh|Mac OS X/.test(ua)) {
|
|
// Apple Silicon vs Intel — UA hints aren't reliable, prefer arm64
|
|
// since modern Macs are predominantly arm64. Users on Intel can
|
|
// pick from "Other platforms".
|
|
detected = 'darwin-arm64';
|
|
platLabel = 'macOS (Apple Silicon)';
|
|
} else if (/Windows/.test(ua)) {
|
|
detected = 'windows-amd64';
|
|
platLabel = 'Windows (x86_64)';
|
|
}
|
|
|
|
var primary = document.getElementById('dl-primary-binary');
|
|
var primaryLabel = document.getElementById('dl-primary-platlabel');
|
|
var primaryMeta = document.getElementById('dl-primary-meta');
|
|
var others = document.getElementById('dl-others');
|
|
|
|
function isChannel(v) {
|
|
return v === 'stable' || v === 'beta' || v === 'alpha';
|
|
}
|
|
function platBinaryName(slug, plat) {
|
|
// slug is a channel name ("stable") or a pinned version ("v0.0.8").
|
|
// The on-disk name uses the slug as-is in both cases since the
|
|
// channel-mirror filenames are zddc-server_<channel>_<plat> and
|
|
// per-version are zddc-server_v<X.Y.Z>_<plat>.
|
|
var suf = (plat.indexOf('windows') === 0) ? '.exe' : '';
|
|
return 'zddc-server_' + slug + '_' + plat + suf;
|
|
}
|
|
function htmlAssetName(tool, slug) {
|
|
return tool + '_' + slug + '.html';
|
|
}
|
|
|
|
// Promote the detected platform to the primary CTA. The secondary
|
|
// row keeps all four; the matching one is hidden to avoid showing
|
|
// the same download twice.
|
|
if (primary) {
|
|
primary.dataset.platform = detected;
|
|
if (primaryLabel) primaryLabel.textContent = 'for ' + platLabel;
|
|
}
|
|
if (others) {
|
|
others.querySelectorAll('a[data-platform="' + detected + '"]').forEach(function(a) {
|
|
a.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
// Single source of truth: the dropdown's current value drives every
|
|
// download link's href. Static markup ships with the stable-channel
|
|
// mirror (`<tool>_stable.html`, `zddc-server_stable_<plat>`) so the
|
|
// page works fully without JS — the JS just keeps things in sync
|
|
// when the user picks a different channel or pins a version.
|
|
var picker = document.getElementById('version-picker');
|
|
if (!picker) return;
|
|
|
|
function rewire(slug) {
|
|
// slug ∈ {"stable", "beta", "alpha"} | "v<X.Y.Z>". Every link with
|
|
// a data-tool attribute is a download URL the dropdown owns.
|
|
document.querySelectorAll('[data-tool]').forEach(function(a) {
|
|
var tool = a.dataset.tool;
|
|
var plat = a.dataset.platform || '';
|
|
if (tool === 'zddc-server') {
|
|
a.href = plat ? platBinaryName(slug, plat) : ('zddc-server_' + slug + '.html');
|
|
} else {
|
|
a.href = htmlAssetName(tool, slug);
|
|
}
|
|
});
|
|
if (primary && primaryMeta) {
|
|
primaryMeta.textContent = primary.getAttribute('href');
|
|
}
|
|
}
|
|
|
|
picker.addEventListener('change', function() { rewire(picker.value); });
|
|
|
|
// Run rewire once on load to apply the platform-detection result
|
|
// (the static href for the primary button is for linux-amd64; on a
|
|
// non-linux client, that needs to flip to the detected platform).
|
|
rewire(picker.value);
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|