Skip to content

Commit 2e9778d

Browse files
the download button stops 404ing, and stops needing a rebuild
FunctionStore_tools_2025.tox has not existed in the bucket since the v3.0.0 rename -- every "Get FNSTools" button on the site pointed at a 404, in latest/ and in every pinned release alike. The bootstrap is FNSTools.tox; publish.py and the manifest rails have said so all along. The hrefs now use the latest/ aliases upload.py publishes for exactly this, so a release cannot leave them serving stale bytes and a version bump needs no site rebuild. Installs stay pinned: latest/ is the human path, and the runtime fetch upgrades hrefs to the manifest's release once the bucket sends CORS -- neither host does today. Only the version label is stamped now. A stale label is cosmetic; it sits beside a download that is still correct. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 015d996 commit 2e9778d

3 files changed

Lines changed: 50 additions & 35 deletions

File tree

website/README.md

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -197,22 +197,30 @@ published than the one the download links point at.
197197

198198
## Release links
199199

200-
Download buttons are stamped with the published release at build time,
201-
read from the rolling manifest at
200+
Download buttons point at the **mutable `latest/` aliases**
201+
(`latest/FNSTools.tox`, `latest/FNS_Installer.tox`) that `upload.py`
202+
publishes beside each release. That is deliberate: a release cannot leave
203+
the buttons serving bytes that are no longer current, so **a version bump
204+
needs no site rebuild**. `latest/` is for humans only — installs still
205+
resolve pinned URLs from the manifest, because reproducible installs are
206+
what make bug reports correlatable (`publish.py`, "Never publish a mutable
207+
`latest/<Package>.tox`").
208+
209+
Only the visible version **label** is stamped at build time, read from the
210+
rolling manifest at
202211
`https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/manifest.json`.
203-
If that fetch fails the build says so and keeps the release already in
204-
`index.html`, so the links always point at something real.
205-
206-
The page also tries to refresh them at runtime, but **that fetch is
207-
currently blocked**: the r2.dev bucket sends no
208-
`Access-Control-Allow-Origin` header. Enabling CORS on the bucket would
209-
make the page self-update between deploys. Until then, re-run the build
210-
after each release.
211-
212-
Note the artifact is still named `FunctionStore_tools_2025.tox` — the
213-
bucket path is already `fnstools`, but the `.tox` filenames have not been
214-
renamed. The filename is a constant in `index.html` and in
215-
`tools/build-site.mjs`; do not assume it tracks the brand.
212+
A stale label is cosmetic: it sits next to a download that is still
213+
correct. Rebuild after a release if you want the number to match.
214+
215+
The page also tries to refresh label and hrefs at runtime, but **that fetch
216+
is currently blocked**: neither the r2.dev bucket nor
217+
`storage.functionstr.com` sends an `Access-Control-Allow-Origin` header.
218+
Enabling CORS on the bucket would make the label self-correcting and would
219+
upgrade the hrefs from `latest/` to the pinned release in the browser.
220+
221+
The bootstrap artifact is `FNSTools.tox`, renamed from
222+
`FunctionStore_tools_2025.tox` in the v3.0.0 redesign. The filename is a
223+
constant in `index.html`; do not assume it tracks the brand.
216224

217225
## Brand assets
218226

website/index.html

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@
349349
<a href="#credits">Credits</a>
350350
<a href="https://patreon.com/function_store" target="_blank" rel="noopener">Patreon</a>
351351
<a class="btn btn-secondary" href="https://github.com/function-store/FunctionStore_tools" target="_blank" rel="noopener">GitHub</a>
352-
<a class="btn btn-primary js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/v3.0.1/FunctionStore_tools_2025.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
352+
<a class="btn btn-primary js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/latest/FNSTools.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
353353
</nav>
354354
</div>
355355
</header>
@@ -364,7 +364,7 @@ <h1 class="hero-title">TouchDesigner,<br />minus the busywork.</h1>
364364
Take the whole toolkit or pick the three tools you actually want.
365365
</p>
366366
<div class="hero-cta">
367-
<a class="btn btn-primary btn-lg js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/v3.0.1/FunctionStore_tools_2025.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
367+
<a class="btn btn-primary btn-lg js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/latest/FNSTools.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
368368
<a class="btn btn-secondary btn-lg" href="/docs/">Read the docs</a>
369369
</div>
370370
<ul class="hero-meta">
@@ -402,8 +402,8 @@ <h3>Drop one <code>.tox</code></h3>
402402
arrives empty — it carries the installer, the updater and nothing else yet.
403403
The container you drop <em>is</em> the install target.
404404
</p>
405-
<a class="btn btn-primary js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/v3.0.1/FunctionStore_tools_2025.tox" download>Download<span class="js-fns-ver">v3.0.1</span></a>
406-
<p class="path-note">Already have a toolkit container? Grab the <a class="js-fns-installer" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/v3.0.1/FNS_Installer.tox" download>bare installer</a> instead (~14 KB).</p>
405+
<a class="btn btn-primary js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/latest/FNSTools.tox" download>Download<span class="js-fns-ver">v3.0.1</span></a>
406+
<p class="path-note">Already have a toolkit container? Grab the <a class="js-fns-installer" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/latest/FNS_Installer.tox" download>bare installer</a> instead (~14 KB).</p>
407407
<p class="path-note">No download at all: <a href="/get/">pick your tools online</a> and paste one line into the Textport — it fetches and verifies everything itself.</p>
408408
</div>
409409
<div class="path">
@@ -437,7 +437,7 @@ <h2>Three steps, no setup files</h2>
437437
</div>
438438
<div class="quickstart">
439439
<ol>
440-
<li>Drop <code>FunctionStore_tools_2025.tox</code> into the root (<code>/</code>) of a project.</li>
440+
<li>Drop <code>FNSTools.tox</code> into the root (<code>/</code>) of a project.</li>
441441
<li>On the <code>FNS_Installer</code> inside it, pulse <strong>Pick Tools</strong>. On the first run it fetches the catalogue and tells you it is doing so.</li>
442442
<li>Pick your tools, hit <strong>Review install…</strong>, read the plan, hit <strong>Install</strong>. The packages land in the container you dropped.</li>
443443
</ol>
@@ -861,7 +861,7 @@ <h2 style="font-size: clamp(28px, 3.6vw, 36px); font-weight: 700; letter-spacing
861861
One <code>.tox</code>, then pick what you need. It is free, and it takes about a minute.
862862
</p>
863863
<div class="hero-cta">
864-
<a class="btn btn-primary btn-lg js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/v3.0.1/FunctionStore_tools_2025.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
864+
<a class="btn btn-primary btn-lg js-fns-download" href="https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/latest/FNSTools.tox" download>Get FNSTools<span class="js-fns-ver">v3.0.1</span></a>
865865
<a class="btn btn-secondary btn-lg" href="/docs/">Read the docs</a>
866866
</div>
867867
</div>
@@ -892,12 +892,15 @@ <h2 style="font-size: clamp(28px, 3.6vw, 36px); font-weight: 700; letter-spacing
892892
// make the page self-refresh between deploys. Either way the static hrefs
893893
// point at a release that exists.
894894
//
895-
// The artifact is still named FunctionStore_tools_2025.tox: the bucket path
896-
// is already `fnstools` but the .tox filenames have not been renamed yet.
897-
// Read the name from here rather than assuming it matches the brand.
895+
// The static hrefs point at latest/, the mutable human aliases upload.py
896+
// publishes beside each release -- so a release never leaves the download
897+
// buttons pointing at bytes that are no longer current, with no rebuild.
898+
// Installs still resolve pinned: when the fetch below succeeds it upgrades
899+
// every href to the release the manifest names, which is the reproducible
900+
// URL. Until the bucket sends CORS the static latest/ href is what serves.
898901
(function () {
899902
var BASE = 'https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools';
900-
var BOOTSTRAP = 'FunctionStore_tools_2025.tox';
903+
var BOOTSTRAP = 'FNSTools.tox';
901904
var INSTALLER = 'FNS_Installer.tox';
902905

903906
function setAll(sel, fn) {

website/tools/build-site.mjs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,17 @@ ${items}
416416
</div>`;
417417
}).filter(Boolean).join('\n');
418418

419-
// The published release, stamped into the static hrefs at build time.
419+
// The published release, stamped into the version LABEL at build time.
420420
//
421-
// The page also refreshes these at runtime, but that fetch cannot be relied
422-
// on: the r2.dev bucket serves no Access-Control-Allow-Origin header, so the
423-
// browser blocks it (TDMap's site has the same silent failure). Stamping here
424-
// is what actually keeps the download links current — the runtime fetch only
425-
// helps if CORS is enabled on the bucket later.
421+
// The hrefs themselves are no longer stamped: they point at the mutable
422+
// latest/ aliases, so a release cannot leave them serving stale bytes even
423+
// if nobody rebuilds. Only the visible "v3.0.1" text is stamped, and it is
424+
// cosmetic — a stale label sits next to a download that is still correct.
425+
//
426+
// The page also refreshes both at runtime, but that fetch cannot be relied
427+
// on: neither the r2.dev bucket nor storage.functionstr.com serves an
428+
// Access-Control-Allow-Origin header, so the browser blocks it. Enabling
429+
// CORS on the bucket is what would make the label self-correcting too.
426430
async function publishedRelease() {
427431
// CI sets this. Without it the stamped release depends on what is published
428432
// at the moment the build runs, so a release cut between commit and CI would
@@ -461,20 +465,20 @@ if (fs.existsSync(landing)) {
461465
`$1${pages.length}$2`);
462466

463467
if (live) {
464-
out = out.replace(/(r2\.dev\/fnstools\/)v[^/"]+\//g, `$1${live.release}/`);
468+
// Only the label. The hrefs stay on latest/ -- see publishedRelease().
465469
// No leading space: the span sits inside a .btn, which is inline-flex
466470
// with its own 8px gap, so one would render as a double space.
467471
out = out.replace(/(<span class="js-fns-ver">)[^<]*(<\/span>)/g,
468472
`$1${live.release}$2`);
469-
console.log(`stamped release ${live.release} (${live.packages?.length ?? '?'} packages published)`);
473+
console.log(`stamped label ${live.release} (${live.packages?.length ?? '?'} packages published)`);
470474
if (live.packages && live.packages.length !== pages.length) {
471475
console.log(`note: catalog has ${pages.length} packages but ${live.release} publishes ` +
472476
`${live.packages.length} — the site lists the catalog, so these align at the next publish`);
473477
}
474478
} else if (process.env.FNSTOOLS_NO_RELEASE_FETCH) {
475-
console.log('release fetch skipped — download links keep the release already in index.html');
479+
console.log('release fetch skipped — version label keeps whatever index.html already says');
476480
} else {
477-
console.log('note: could not reach the release manifest — download links keep the release already in index.html');
481+
console.log('note: could not reach the release manifest — version label keeps whatever index.html already says');
478482
}
479483
fs.writeFileSync(landing, out);
480484
} else {

0 commit comments

Comments
 (0)