Commit Graph
2 Commits
Author SHA1 Message Date
bdeshi 7da2a58fd5 generate sized derivatives ahead of the request
A pass over the content at startup writes three widths per picture into a cache
outside the site root, named by the source's content hash and the width (ADR-0042).
Idempotent by construction: a rerun stats and skips, an edited picture takes a new
name, and nothing stale can be served under an old one. Restarting the evidence
site made 0 derivatives the second time, as it should.

Ahead of the request rather than during it, because resampling is felt and there is
no page cache yet to hide it. Outside the site root, because the engine reads that
directory and must not leave generated files in somebody's content git — a lost
cache costs one startup pass and no correctness.

Markup now carries the original as src, the derivatives as srcset closed by the
original at its own width, and width/height from the original — which retires most
of the latent row about the output floor; only a gallery's alt is still empty, and
a filename cannot supply that.

Two things the work itself decided:

`Fragment.Items` became `Fragment.Pictures`, ADR-0037's own revisit trigger. Items
had one consumer, so widening it beat adding a second list beside it.

"A browser can show it" and "we can resample it" are different questions, and
conflating them nearly deleted content: an SVG has no decoder here, so a single
predicate would have dropped SVGs from galleries silently. Undecodable and
unsupported pictures are now rendered as they are, without a size or a srcset.
2026-08-01 02:23:36 +06:00
bdeshi 98a973db83 serve a declared slug as an address, leaving the key alone
The human chose the second option: a route sits beside the key rather than
replacing it. So `slug` renames what a bundle is served at, in every language, and
identity stays derived from the path — which is exactly what keeps ADR-0033 intact,
since series membership is the directory. A series landing page can now be renamed
without orphaning its chapters, and there is a test that says so.

`Site` resolves routes at index time, because only it can see whether every variant
agrees. Disagreement is dropped rather than resolved, as is a slug landing where
another bundle already answers — the same rule colliding keys and contested aliases
already follow. The key a slug moved away from stops answering, so the old address
does not quietly keep working.

Two bugs surfaced doing this, both older than this change:

An alias naming its own bundle's former key was rejected as "an alias that names a
real bundle" — which made rename-plus-alias, the entire point of ADR-0008's alias
mechanism, impossible. The check now asks what a request asks: is anything actually
served there.

Aliases were counted per declaring *file*, so a bundle whose two language variants
both listed the same alias looked like two rival claimants and lost the alias. It is
a set of keys now. This one only appears with translated content, which is why no
fixture had caught it since entry 4 — the real binary did, on the first multilingual
rename.
2026-08-01 02:23:36 +06:00