chadtmiller.com/knotless

Git hosted in your atproto account, on any stock PDS, fast enough for agents.

git clone knotless://chadtmiller.com/knotless

needs the knotless git helper. set it up

Page answers revalidated, even at a commit hash

An answer under /_data at a commit hash was sent as immutable for a year,
though it shows the repository as it is now (description, picture,
counts), its authors' accounts, and a shape a release can change. A
browser that kept one from before the last release threw on following a
link to a commit page, while a reload, drawn on the server, worked. Every
page answer is now no-cache, as a branch's already was; a file at a hash
stays immutable. The pages ask for their answers with cache: no-cache,
past any a browser still holds from before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chad Miller and Claude Opus 5.5 committed on Oct 21, 2026 parent 803af72 commit aa2df3f
Showing 101 changed files with 177 additions and 195 deletions
README.md+1−1
@@ -279,7 +279,7 @@ rebuilds the index.
numbers, syntax highlighting, and the changed part of each edited line.
Code is sent as plain text and highlighted with tree-sitter ranges applied
by the CSS Custom Highlight API; links load on hover; pages move with
view transitions; anything named by a commit hash is cached as immutable.
view transitions; files named by a commit hash are cached as immutable.
The front page, repositories, pulls and issues unfurl into a social card,
drawn in process. Writing is for git, the CLI and agents.
crates/knotless-serve/src/web.rs+75−94
@@ -120,8 +120,8 @@ fn url_path(path: &str) -> String {
out
}
/// Caching for an answer about `rev`: forever when it names a commit by
/// hash, else checked again each time, as a branch can move.
/// Caching for a file at `rev`: forever when it names a commit by hash,
/// else checked again each time, as a branch can move.
fn cache_for(rev: &str) -> &'static str {
if read::is_pinned(rev) {
"public, max-age=31536000, immutable"
@@ -130,11 +130,13 @@ fn cache_for(rev: &str) -> &'static str {
}
}
/// `value` as the answer, cached as `cache` says.
fn answer<T: Serialize>(cache: &'static str, value: T) -> Response {
/// `value` as the answer, checked again each time: even at a commit hash
/// it shows the repository as it is now, its authors' accounts, and a shape
/// a later release may change.
fn answer<T: Serialize>(value: T) -> Response {
let mut res = axum::Json(value).into_response();
res.headers_mut()
.insert(header::CACHE_CONTROL, HeaderValue::from_static(cache));
.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-cache"));
res
}
@@ -677,7 +679,7 @@ async fn search(State(app): State<Arc<App>>, Query(query): Query<SearchQuery>) -
private: false,
})
.collect();
Ok(answer("no-cache", Search { query: q, repos }))
Ok(answer(Search { query: q, repos }))
}
/// An account: who it is, as its Bluesky profile says if it has one, and
@@ -744,18 +746,15 @@ async fn profile(State(app): State<Arc<App>>, Path(authority): Path<String>) ->
created_at: r.value.created_at,
})
.collect();
Ok(answer(
"no-cache",
Profile {
did,
handle: shown,
name,
bio: text("description"),
avatar,
about: about["description"].as_str().map(|bio| summary(bio, 200)),
repos,
},
))
Ok(answer(Profile {
did,
handle: shown,
name,
bio: text("description"),
avatar,
about: about["description"].as_str().map(|bio| summary(bio, 200)),
repos,
}))
}
type RepoPath = Path<(String, String)>;
@@ -810,7 +809,7 @@ async fn code(State(app): State<Arc<App>>, Path((authority, name)): RepoPath) ->
entries: Vec::new(),
readme: None,
};
return Ok(answer("no-cache", empty));
return Ok(answer(empty));
}
listing(&app, &repo, &head, "").await
}
@@ -870,18 +869,15 @@ async fn listing(app: &App, repo: &Repo, rev: &str, path: &str) -> Result<Respon
size: e.size,
})
.collect();
Ok(answer(
cache_for(rev),
Listing {
repo: head,
rev: rev.to_string(),
path: path.to_string(),
empty: false,
last: shown(app, repo, last).await.pop(),
entries,
readme,
},
))
Ok(answer(Listing {
repo: head,
rev: rev.to_string(),
path: path.to_string(),
empty: false,
last: shown(app, repo, last).await.pop(),
entries,
readme,
}))
}
/// Markdown, with raw HTML shown as text and links made relative to the
@@ -993,19 +989,16 @@ async fn blob(
.map(|r| r.encode())
.unwrap_or_default()
});
Ok(answer(
cache_for(&rev),
Blob {
repo: repo.head(&app).await,
path: path.to_string(),
shown: shown.to_string(),
size: bytes.len() as u64,
lines: text.lines().count().max(1),
text: ranges.is_some().then(|| text.into_owned()),
ranges,
rev,
},
))
Ok(answer(Blob {
repo: repo.head(&app).await,
path: path.to_string(),
shown: shown.to_string(),
size: bytes.len() as u64,
lines: text.lines().count().max(1),
text: ranges.is_some().then(|| text.into_owned()),
ranges,
rev,
}))
}
/// The file itself. Never run as a page: sandboxed, and typed only as text
@@ -1068,17 +1061,14 @@ async fn commits(
.objects()?
.log(&rev, path, page * COMMITS_PER_PAGE, COMMITS_PER_PAGE)
.map_err(not_found)?;
Ok(answer(
cache_for(&rev),
History {
repo: repo.head(&app).await,
path: path.to_string(),
page,
more: log.len() == COMMITS_PER_PAGE,
commits: shown(&app, &repo, log).await,
rev,
},
))
Ok(answer(History {
repo: repo.head(&app).await,
path: path.to_string(),
page,
more: log.len() == COMMITS_PER_PAGE,
commits: shown(&app, &repo, log).await,
rev,
}))
}
/// One row of a file's diff: a hunk header, a note, or a line with its old
@@ -1209,14 +1199,11 @@ async fn commit(
.await
.map_err(not_found)?;
let files = diff::parse(&patch).into_iter().map(file_diff).collect();
Ok(answer(
cache_for(&rev),
Change {
repo: repo.head(&app).await,
commit: c,
files,
},
))
Ok(answer(Change {
repo: repo.head(&app).await,
commit: c,
files,
}))
}
#[derive(Deserialize, Default)]
@@ -1325,17 +1312,14 @@ async fn items(
comments: i.comments,
});
}
Ok(answer(
"no-cache",
Items {
repo: repo.head(&app).await,
kind: kind.to_string(),
open,
opened: counts.0,
closed: counts.1,
items,
},
))
Ok(answer(Items {
repo: repo.head(&app).await,
kind: kind.to_string(),
open,
opened: counts.0,
closed: counts.1,
items,
}))
}
/// Something said on a pull or an issue, made into HTML.
@@ -1453,26 +1437,23 @@ async fn item(
verdict: c.value["verdict"].as_str().map(str::to_string),
})
.collect();
Ok(answer(
"no-cache",
Discussion {
repo: repo.head(&app).await,
kind,
body: item.body.as_deref().map(|b| markdown(b, &base, &base)),
title: item.title,
state: item.state,
author,
avatar: avatar(&app, &item.author).await,
created_at: item.created_at,
from,
branch: item.head.map(|h| h.branch),
base: item.base,
comments: said,
merged: item.merged,
about,
card,
},
))
Ok(answer(Discussion {
repo: repo.head(&app).await,
kind,
body: item.body.as_deref().map(|b| markdown(b, &base, &base)),
title: item.title,
state: item.state,
author,
avatar: avatar(&app, &item.author).await,
created_at: item.created_at,
from,
branch: item.head.map(|h| h.branch),
base: item.base,
comments: said,
merged: item.merged,
about,
card,
}))
}
static CARDS: LazyLock<card::Cache> = LazyLock::new(|| card::Cache::new(512));
crates/knotless-serve/tests/web.rs+3−5
@@ -265,7 +265,8 @@ fn browsing_a_repository() {
.unwrap();
assert_eq!(res.headers()["content-encoding"], "br");
// A branch with a slash in its name, and a pinned commit, which never changes.
// A branch with a slash in its name, and a pinned commit, whose answer is
// still checked again: it shows the repository as it is now.
let sub = site.data(&format!("{repo}/tree/feature/x/src"));
assert_eq!(
(sub["rev"].as_str(), sub["path"].as_str()),
@@ -273,10 +274,7 @@ fn browsing_a_repository() {
);
assert_eq!(names(&sub["entries"]), ["main.rs"]);
let res = site.get(&format!("/_data{repo}/tree/{tip}/docs"));
assert_eq!(
res.headers()["cache-control"],
"public, max-age=31536000, immutable"
);
assert_eq!(res.headers()["cache-control"], "no-cache");
let docs: Value = res.json().unwrap();
assert_eq!(docs["readme"]["text"], "plain <words>\n");
assert_eq!(docs["readme"]["html"], Value::Null);
docs/design.md+3−2
@@ -436,8 +436,9 @@ scripts, allowed by hash in a `default-src 'none'` content security policy:
- **Navigation.** Speculation rules prerender a same-site link as the
pointer settles on it, and cross-document view transitions keep the
header still between pages.
- **Caching.** Pages named by a commit hash are immutable; pages named by a
branch are revalidated. HTML is compressed; git responses are not.
- **Caching.** Files named by a commit hash are immutable; pages are
revalidated, even at a hash, as they show the repository as it is now
and their answers' shape can change with a release. HTML is compressed; git responses are not.
- **Social cards.** The front page, each repository's pages, and each pull
and issue name a 1200×630 PNG in Open Graph tags, at the page's path
plus `/card.png`. A card is an SVG written like the pages, drawn by
harness/shots/baseline/darwin/commit-desktop-dark.sha256+1−1
@@ -1 +1 @@
d7388bde511d27eacb4d0a8d20e5dee223c08014ba808bceac6f5226a05649b6
\ No newline at end of file
818fa06b1837c01e521ea504bc5f4d0d760cfe971371b0b8e537e2e778001df2
\ No newline at end of file
harness/shots/baseline/darwin/commit-desktop-light.sha256+1−1
@@ -1 +1 @@
d7388bde511d27eacb4d0a8d20e5dee223c08014ba808bceac6f5226a05649b6
\ No newline at end of file
818fa06b1837c01e521ea504bc5f4d0d760cfe971371b0b8e537e2e778001df2
\ No newline at end of file
harness/shots/baseline/darwin/commit-phone-dark.sha256+1−1
@@ -1 +1 @@
d7388bde511d27eacb4d0a8d20e5dee223c08014ba808bceac6f5226a05649b6
\ No newline at end of file
818fa06b1837c01e521ea504bc5f4d0d760cfe971371b0b8e537e2e778001df2
\ No newline at end of file
harness/shots/baseline/darwin/commit-phone-light.sha256+1−1
@@ -1 +1 @@
d7388bde511d27eacb4d0a8d20e5dee223c08014ba808bceac6f5226a05649b6
\ No newline at end of file
818fa06b1837c01e521ea504bc5f4d0d760cfe971371b0b8e537e2e778001df2
\ No newline at end of file
harness/shots/baseline/darwin/commits-desktop-dark.sha256+1−1
@@ -1 +1 @@
bda55bd4f89cedd3f2651037b365d711b22bdd6324558f2ba6f24410e31d1513
\ No newline at end of file
5161ee751b388cdc3a9779e015bae6086f6a61ebd2b049a2b33fa840cf32c190
\ No newline at end of file
harness/shots/baseline/darwin/commits-desktop-light.sha256+1−1
@@ -1 +1 @@
bda55bd4f89cedd3f2651037b365d711b22bdd6324558f2ba6f24410e31d1513
\ No newline at end of file
5161ee751b388cdc3a9779e015bae6086f6a61ebd2b049a2b33fa840cf32c190
\ No newline at end of file
harness/shots/baseline/darwin/commits-phone-dark.sha256+1−1
@@ -1 +1 @@
bda55bd4f89cedd3f2651037b365d711b22bdd6324558f2ba6f24410e31d1513
\ No newline at end of file
5161ee751b388cdc3a9779e015bae6086f6a61ebd2b049a2b33fa840cf32c190
\ No newline at end of file
harness/shots/baseline/darwin/commits-phone-light.sha256+1−1
@@ -1 +1 @@
bda55bd4f89cedd3f2651037b365d711b22bdd6324558f2ba6f24410e31d1513
\ No newline at end of file
5161ee751b388cdc3a9779e015bae6086f6a61ebd2b049a2b33fa840cf32c190
\ No newline at end of file
harness/shots/baseline/darwin/directory-desktop-dark.sha256+1−1
@@ -1 +1 @@
5a4e4e2fa4fa923a2fdb9bc286b16e83e19b9a53e12d04fbbbb67f7b8e5512fd
\ No newline at end of file
942a5a14b1c7bd42b6fa3a5713dedccce26dffdaa24e798579efaf8af11d6c61
\ No newline at end of file
harness/shots/baseline/darwin/directory-desktop-light.sha256+1−1
@@ -1 +1 @@
5a4e4e2fa4fa923a2fdb9bc286b16e83e19b9a53e12d04fbbbb67f7b8e5512fd
\ No newline at end of file
942a5a14b1c7bd42b6fa3a5713dedccce26dffdaa24e798579efaf8af11d6c61
\ No newline at end of file
harness/shots/baseline/darwin/directory-phone-dark.sha256+1−1
@@ -1 +1 @@
5a4e4e2fa4fa923a2fdb9bc286b16e83e19b9a53e12d04fbbbb67f7b8e5512fd
\ No newline at end of file
942a5a14b1c7bd42b6fa3a5713dedccce26dffdaa24e798579efaf8af11d6c61
\ No newline at end of file
harness/shots/baseline/darwin/directory-phone-light.sha256+1−1
@@ -1 +1 @@
5a4e4e2fa4fa923a2fdb9bc286b16e83e19b9a53e12d04fbbbb67f7b8e5512fd
\ No newline at end of file
942a5a14b1c7bd42b6fa3a5713dedccce26dffdaa24e798579efaf8af11d6c61
\ No newline at end of file
harness/shots/baseline/darwin/empty-desktop-dark.sha256+1−1
@@ -1 +1 @@
5ad4a8a6896ab5d79d46008f147c96d1e027f632a8e43347c7f66c397a16b095
\ No newline at end of file
860ef909baf32e82e9b41d71edbf37fd3e6d0a34311241e9d84870636b882a75
\ No newline at end of file
harness/shots/baseline/darwin/empty-desktop-light.sha256+1−1
@@ -1 +1 @@
5ad4a8a6896ab5d79d46008f147c96d1e027f632a8e43347c7f66c397a16b095
\ No newline at end of file
860ef909baf32e82e9b41d71edbf37fd3e6d0a34311241e9d84870636b882a75
\ No newline at end of file
harness/shots/baseline/darwin/empty-phone-dark.sha256+1−1
@@ -1 +1 @@
5ad4a8a6896ab5d79d46008f147c96d1e027f632a8e43347c7f66c397a16b095
\ No newline at end of file
860ef909baf32e82e9b41d71edbf37fd3e6d0a34311241e9d84870636b882a75
\ No newline at end of file
harness/shots/baseline/darwin/empty-phone-light.sha256+1−1
@@ -1 +1 @@
5ad4a8a6896ab5d79d46008f147c96d1e027f632a8e43347c7f66c397a16b095
\ No newline at end of file
860ef909baf32e82e9b41d71edbf37fd3e6d0a34311241e9d84870636b882a75
\ No newline at end of file
harness/shots/baseline/darwin/file-desktop-dark.sha256+1−1
@@ -1 +1 @@
954a475e281c0be4d0885b634015ed628c92afdf96362561dc8afaf509ff6c40
\ No newline at end of file
a7799b75b16d7155ccd1169ee3b89b5686028258bd8009979f2f94c35d22bb90
\ No newline at end of file
harness/shots/baseline/darwin/file-desktop-light.sha256+1−1
@@ -1 +1 @@
954a475e281c0be4d0885b634015ed628c92afdf96362561dc8afaf509ff6c40
\ No newline at end of file
a7799b75b16d7155ccd1169ee3b89b5686028258bd8009979f2f94c35d22bb90
\ No newline at end of file
harness/shots/baseline/darwin/file-phone-dark.sha256+1−1
@@ -1 +1 @@
954a475e281c0be4d0885b634015ed628c92afdf96362561dc8afaf509ff6c40
\ No newline at end of file
a7799b75b16d7155ccd1169ee3b89b5686028258bd8009979f2f94c35d22bb90
\ No newline at end of file
harness/shots/baseline/darwin/file-phone-light.sha256+1−1
@@ -1 +1 @@
954a475e281c0be4d0885b634015ed628c92afdf96362561dc8afaf509ff6c40
\ No newline at end of file
a7799b75b16d7155ccd1169ee3b89b5686028258bd8009979f2f94c35d22bb90
\ No newline at end of file
harness/shots/baseline/darwin/fork-desktop-dark.sha256+1−1
@@ -1 +1 @@
fd1fbfe20fbc3c2cad0426bbea857712cd0952df28ed8a0875a51353261e989a
\ No newline at end of file
3611a30bf8ce7de1460ae56fa9901eb35700e4261c086e302df7710dc28b33de
\ No newline at end of file
harness/shots/baseline/darwin/fork-desktop-light.sha256+1−1
@@ -1 +1 @@
fd1fbfe20fbc3c2cad0426bbea857712cd0952df28ed8a0875a51353261e989a
\ No newline at end of file
3611a30bf8ce7de1460ae56fa9901eb35700e4261c086e302df7710dc28b33de
\ No newline at end of file
harness/shots/baseline/darwin/fork-phone-dark.sha256+1−1
@@ -1 +1 @@
fd1fbfe20fbc3c2cad0426bbea857712cd0952df28ed8a0875a51353261e989a
\ No newline at end of file
3611a30bf8ce7de1460ae56fa9901eb35700e4261c086e302df7710dc28b33de
\ No newline at end of file
harness/shots/baseline/darwin/fork-phone-light.sha256+1−1
@@ -1 +1 @@
fd1fbfe20fbc3c2cad0426bbea857712cd0952df28ed8a0875a51353261e989a
\ No newline at end of file
3611a30bf8ce7de1460ae56fa9901eb35700e4261c086e302df7710dc28b33de
\ No newline at end of file
harness/shots/baseline/darwin/home-desktop-dark.sha256+1−1
@@ -1 +1 @@
d92704aeb8d9f2379f2b5e7757ffa4caa374a632356883a0e0355f4f9d2ce48c
\ No newline at end of file
99b44bcfa119a5ebe2b19723c73a1192e2bc475ab621b6511dc144539b1247cb
\ No newline at end of file
harness/shots/baseline/darwin/home-desktop-light.sha256+1−1
@@ -1 +1 @@
d92704aeb8d9f2379f2b5e7757ffa4caa374a632356883a0e0355f4f9d2ce48c
\ No newline at end of file
99b44bcfa119a5ebe2b19723c73a1192e2bc475ab621b6511dc144539b1247cb
\ No newline at end of file
harness/shots/baseline/darwin/home-phone-dark.sha256+1−1
@@ -1 +1 @@
d92704aeb8d9f2379f2b5e7757ffa4caa374a632356883a0e0355f4f9d2ce48c
\ No newline at end of file
99b44bcfa119a5ebe2b19723c73a1192e2bc475ab621b6511dc144539b1247cb
\ No newline at end of file
harness/shots/baseline/darwin/home-phone-light.sha256+1−1
@@ -1 +1 @@
d92704aeb8d9f2379f2b5e7757ffa4caa374a632356883a0e0355f4f9d2ce48c
\ No newline at end of file
99b44bcfa119a5ebe2b19723c73a1192e2bc475ab621b6511dc144539b1247cb
\ No newline at end of file
harness/shots/baseline/darwin/image-desktop-dark.sha256+1−1
@@ -1 +1 @@
a4035513e7889066b45d946888db5037140ab03fdccba215488a47676d6530a9
\ No newline at end of file
faa82cbcf4a71362649f15fd127729a73beb593c3189ef2a55f099dfce03831d
\ No newline at end of file
harness/shots/baseline/darwin/image-desktop-light.sha256+1−1
@@ -1 +1 @@
a4035513e7889066b45d946888db5037140ab03fdccba215488a47676d6530a9
\ No newline at end of file
faa82cbcf4a71362649f15fd127729a73beb593c3189ef2a55f099dfce03831d
\ No newline at end of file
harness/shots/baseline/darwin/image-phone-dark.sha256+1−1
@@ -1 +1 @@
a4035513e7889066b45d946888db5037140ab03fdccba215488a47676d6530a9
\ No newline at end of file
faa82cbcf4a71362649f15fd127729a73beb593c3189ef2a55f099dfce03831d
\ No newline at end of file
harness/shots/baseline/darwin/image-phone-light.sha256+1−1
@@ -1 +1 @@
a4035513e7889066b45d946888db5037140ab03fdccba215488a47676d6530a9
\ No newline at end of file
faa82cbcf4a71362649f15fd127729a73beb593c3189ef2a55f099dfce03831d
\ No newline at end of file
harness/shots/baseline/darwin/issue-closed-desktop-dark.sha256+1−1
@@ -1 +1 @@
51df5a974b7d30e0c511dd4f14911605f20d038ee7e2e347bbc2dec5393a1658
\ No newline at end of file
0fe3adabb4fee61108049f554ef0f5ab3763f6a354658154b62826ceeb5d3782
\ No newline at end of file
harness/shots/baseline/darwin/issue-closed-desktop-light.sha256+1−1
@@ -1 +1 @@
51df5a974b7d30e0c511dd4f14911605f20d038ee7e2e347bbc2dec5393a1658
\ No newline at end of file
0fe3adabb4fee61108049f554ef0f5ab3763f6a354658154b62826ceeb5d3782
\ No newline at end of file
harness/shots/baseline/darwin/issue-closed-phone-dark.sha256+1−1
@@ -1 +1 @@
51df5a974b7d30e0c511dd4f14911605f20d038ee7e2e347bbc2dec5393a1658
\ No newline at end of file
0fe3adabb4fee61108049f554ef0f5ab3763f6a354658154b62826ceeb5d3782
\ No newline at end of file
harness/shots/baseline/darwin/issue-closed-phone-light.sha256+1−1
@@ -1 +1 @@
51df5a974b7d30e0c511dd4f14911605f20d038ee7e2e347bbc2dec5393a1658
\ No newline at end of file
0fe3adabb4fee61108049f554ef0f5ab3763f6a354658154b62826ceeb5d3782
\ No newline at end of file
harness/shots/baseline/darwin/issue-desktop-dark.sha256+1−1
@@ -1 +1 @@
bd833d088c6345100e9608effac750311bf7735df535e75aca9f210dc0d7e973
\ No newline at end of file
4f849606f630279031ecb50e66640f5b8a99f065fc61b916ef286649ee72c8fd
\ No newline at end of file
harness/shots/baseline/darwin/issue-desktop-light.sha256+1−1
@@ -1 +1 @@
bd833d088c6345100e9608effac750311bf7735df535e75aca9f210dc0d7e973
\ No newline at end of file
4f849606f630279031ecb50e66640f5b8a99f065fc61b916ef286649ee72c8fd
\ No newline at end of file
harness/shots/baseline/darwin/issue-phone-dark.sha256+1−1
@@ -1 +1 @@
bd833d088c6345100e9608effac750311bf7735df535e75aca9f210dc0d7e973
\ No newline at end of file
4f849606f630279031ecb50e66640f5b8a99f065fc61b916ef286649ee72c8fd
\ No newline at end of file
harness/shots/baseline/darwin/issue-phone-light.sha256+1−1
@@ -1 +1 @@
bd833d088c6345100e9608effac750311bf7735df535e75aca9f210dc0d7e973
\ No newline at end of file
4f849606f630279031ecb50e66640f5b8a99f065fc61b916ef286649ee72c8fd
\ No newline at end of file
harness/shots/baseline/darwin/issues-closed-desktop-dark.sha256+1−1
@@ -1 +1 @@
36444fee9d691bb1b4d440209ea098e39ca3ec2dd19623b1990e649bd31df536
\ No newline at end of file
3ebe5b3c8637c4edd103ab358e7b75663ee4e859ed11d936379ecc0fe76bc205
\ No newline at end of file
harness/shots/baseline/darwin/issues-closed-desktop-light.sha256+1−1
@@ -1 +1 @@
36444fee9d691bb1b4d440209ea098e39ca3ec2dd19623b1990e649bd31df536
\ No newline at end of file
3ebe5b3c8637c4edd103ab358e7b75663ee4e859ed11d936379ecc0fe76bc205
\ No newline at end of file
harness/shots/baseline/darwin/issues-closed-phone-dark.sha256+1−1
@@ -1 +1 @@
36444fee9d691bb1b4d440209ea098e39ca3ec2dd19623b1990e649bd31df536
\ No newline at end of file
3ebe5b3c8637c4edd103ab358e7b75663ee4e859ed11d936379ecc0fe76bc205
\ No newline at end of file
harness/shots/baseline/darwin/issues-closed-phone-light.sha256+1−1
@@ -1 +1 @@
36444fee9d691bb1b4d440209ea098e39ca3ec2dd19623b1990e649bd31df536
\ No newline at end of file
3ebe5b3c8637c4edd103ab358e7b75663ee4e859ed11d936379ecc0fe76bc205
\ No newline at end of file
harness/shots/baseline/darwin/issues-desktop-dark.sha256+1−1
@@ -1 +1 @@
2a72873a2e2e6cc3657ba11901327a3be829087a592ac12fc1a0a6c0f701d107
\ No newline at end of file
a78cf6cbc7fdcfdf7a7feda8bc7d28478707de77f9c82b5867957c42209d4899
\ No newline at end of file
harness/shots/baseline/darwin/issues-desktop-light.sha256+1−1
@@ -1 +1 @@
2a72873a2e2e6cc3657ba11901327a3be829087a592ac12fc1a0a6c0f701d107
\ No newline at end of file
a78cf6cbc7fdcfdf7a7feda8bc7d28478707de77f9c82b5867957c42209d4899
\ No newline at end of file
harness/shots/baseline/darwin/issues-phone-dark.sha256+1−1
@@ -1 +1 @@
2a72873a2e2e6cc3657ba11901327a3be829087a592ac12fc1a0a6c0f701d107
\ No newline at end of file
a78cf6cbc7fdcfdf7a7feda8bc7d28478707de77f9c82b5867957c42209d4899
\ No newline at end of file
harness/shots/baseline/darwin/issues-phone-light.sha256+1−1
@@ -1 +1 @@
2a72873a2e2e6cc3657ba11901327a3be829087a592ac12fc1a0a6c0f701d107
\ No newline at end of file
a78cf6cbc7fdcfdf7a7feda8bc7d28478707de77f9c82b5867957c42209d4899
\ No newline at end of file
harness/shots/baseline/darwin/markdown-desktop-dark.sha256+1−1
@@ -1 +1 @@
6df9521fc724a67815770faa5b5caf94d170b2b83fc0cac975b9ba742642d75c
\ No newline at end of file
9993c9ff2ac56544a7a5a682a5f71995382e0b6d7e936ef64ffd4423c8f945c4
\ No newline at end of file
harness/shots/baseline/darwin/markdown-desktop-light.sha256+1−1
@@ -1 +1 @@
6df9521fc724a67815770faa5b5caf94d170b2b83fc0cac975b9ba742642d75c
\ No newline at end of file
9993c9ff2ac56544a7a5a682a5f71995382e0b6d7e936ef64ffd4423c8f945c4
\ No newline at end of file
harness/shots/baseline/darwin/markdown-phone-dark.sha256+1−1
@@ -1 +1 @@
6df9521fc724a67815770faa5b5caf94d170b2b83fc0cac975b9ba742642d75c
\ No newline at end of file
9993c9ff2ac56544a7a5a682a5f71995382e0b6d7e936ef64ffd4423c8f945c4
\ No newline at end of file
harness/shots/baseline/darwin/markdown-phone-light.sha256+1−1
@@ -1 +1 @@
6df9521fc724a67815770faa5b5caf94d170b2b83fc0cac975b9ba742642d75c
\ No newline at end of file
9993c9ff2ac56544a7a5a682a5f71995382e0b6d7e936ef64ffd4423c8f945c4
\ No newline at end of file
harness/shots/baseline/darwin/missing-desktop-dark.sha256+1−1
@@ -1 +1 @@
844f001041b656a42ed953bbe32ee34cffdddd47d8df7af5ab2bda50c63ca3ad
\ No newline at end of file
a8168a4c67bc5be54bdea4085a2bc03e31cd9025a97b93ba975ae4b6ffcedb02
\ No newline at end of file
harness/shots/baseline/darwin/missing-desktop-light.sha256+1−1
@@ -1 +1 @@
844f001041b656a42ed953bbe32ee34cffdddd47d8df7af5ab2bda50c63ca3ad
\ No newline at end of file
a8168a4c67bc5be54bdea4085a2bc03e31cd9025a97b93ba975ae4b6ffcedb02
\ No newline at end of file
harness/shots/baseline/darwin/missing-phone-dark.sha256+1−1
@@ -1 +1 @@
844f001041b656a42ed953bbe32ee34cffdddd47d8df7af5ab2bda50c63ca3ad
\ No newline at end of file
a8168a4c67bc5be54bdea4085a2bc03e31cd9025a97b93ba975ae4b6ffcedb02
\ No newline at end of file
harness/shots/baseline/darwin/missing-phone-light.sha256+1−1
@@ -1 +1 @@
844f001041b656a42ed953bbe32ee34cffdddd47d8df7af5ab2bda50c63ca3ad
\ No newline at end of file
a8168a4c67bc5be54bdea4085a2bc03e31cd9025a97b93ba975ae4b6ffcedb02
\ No newline at end of file
harness/shots/baseline/darwin/profile-desktop-dark.sha256+1−1
@@ -1 +1 @@
15a94b0bbb15f26a3cbfddf955ad7b528dfb0bd0a1a0537dfab41d0375ab5cd8
\ No newline at end of file
46bc5dcf7a870e59fa00fe6f4255eefb4ab7d5b87617daee420f8a8bb0cca44c
\ No newline at end of file
harness/shots/baseline/darwin/profile-desktop-light.sha256+1−1
@@ -1 +1 @@
15a94b0bbb15f26a3cbfddf955ad7b528dfb0bd0a1a0537dfab41d0375ab5cd8
\ No newline at end of file
46bc5dcf7a870e59fa00fe6f4255eefb4ab7d5b87617daee420f8a8bb0cca44c
\ No newline at end of file
harness/shots/baseline/darwin/profile-fork-desktop-dark.sha256+1−1
@@ -1 +1 @@
7c79e576f32bff157cf49c7b0b42b5d7c4c25ce00e748cb870d575bfe14b11a9
\ No newline at end of file
91e2626e8fe47ff8e71d4992dab3e17e53e078316640c93c35885f8c1b953e7f
\ No newline at end of file
harness/shots/baseline/darwin/profile-fork-desktop-light.sha256+1−1
@@ -1 +1 @@
7c79e576f32bff157cf49c7b0b42b5d7c4c25ce00e748cb870d575bfe14b11a9
\ No newline at end of file
91e2626e8fe47ff8e71d4992dab3e17e53e078316640c93c35885f8c1b953e7f
\ No newline at end of file
harness/shots/baseline/darwin/profile-fork-phone-dark.sha256+1−1
@@ -1 +1 @@
7c79e576f32bff157cf49c7b0b42b5d7c4c25ce00e748cb870d575bfe14b11a9
\ No newline at end of file
91e2626e8fe47ff8e71d4992dab3e17e53e078316640c93c35885f8c1b953e7f
\ No newline at end of file
harness/shots/baseline/darwin/profile-fork-phone-light.sha256+1−1
@@ -1 +1 @@
7c79e576f32bff157cf49c7b0b42b5d7c4c25ce00e748cb870d575bfe14b11a9
\ No newline at end of file
91e2626e8fe47ff8e71d4992dab3e17e53e078316640c93c35885f8c1b953e7f
\ No newline at end of file
harness/shots/baseline/darwin/profile-phone-dark.sha256+1−1
@@ -1 +1 @@
15a94b0bbb15f26a3cbfddf955ad7b528dfb0bd0a1a0537dfab41d0375ab5cd8
\ No newline at end of file
46bc5dcf7a870e59fa00fe6f4255eefb4ab7d5b87617daee420f8a8bb0cca44c
\ No newline at end of file
harness/shots/baseline/darwin/profile-phone-light.sha256+1−1
@@ -1 +1 @@
15a94b0bbb15f26a3cbfddf955ad7b528dfb0bd0a1a0537dfab41d0375ab5cd8
\ No newline at end of file
46bc5dcf7a870e59fa00fe6f4255eefb4ab7d5b87617daee420f8a8bb0cca44c
\ No newline at end of file
harness/shots/baseline/darwin/pull-desktop-dark.sha256+1−1
@@ -1 +1 @@
91e9b0ab3edc32e396e5e69277672f730923ebbd5a226f9b3c8e5205d3ff5a25
\ No newline at end of file
b41cf484a6c00073334832ad4076a61abf64d4875e140351e06ce8462a2cdfe6
\ No newline at end of file
harness/shots/baseline/darwin/pull-desktop-light.sha256+1−1
@@ -1 +1 @@
91e9b0ab3edc32e396e5e69277672f730923ebbd5a226f9b3c8e5205d3ff5a25
\ No newline at end of file
b41cf484a6c00073334832ad4076a61abf64d4875e140351e06ce8462a2cdfe6
\ No newline at end of file
harness/shots/baseline/darwin/pull-open-desktop-dark.sha256+1−1
@@ -1 +1 @@
4353913ac1351bdd1c8fb4aac48129bb65287d80e61c91c91fecc09455e0c749
\ No newline at end of file
4072a18085abe59d6df57ab0a8ed64bda2b53ed6318cdb20ca152dfcc6d973c4
\ No newline at end of file
harness/shots/baseline/darwin/pull-open-desktop-light.sha256+1−1
@@ -1 +1 @@
4353913ac1351bdd1c8fb4aac48129bb65287d80e61c91c91fecc09455e0c749
\ No newline at end of file
4072a18085abe59d6df57ab0a8ed64bda2b53ed6318cdb20ca152dfcc6d973c4
\ No newline at end of file
harness/shots/baseline/darwin/pull-open-phone-dark.sha256+1−1
@@ -1 +1 @@
4353913ac1351bdd1c8fb4aac48129bb65287d80e61c91c91fecc09455e0c749
\ No newline at end of file
4072a18085abe59d6df57ab0a8ed64bda2b53ed6318cdb20ca152dfcc6d973c4
\ No newline at end of file
harness/shots/baseline/darwin/pull-open-phone-light.sha256+1−1
@@ -1 +1 @@
4353913ac1351bdd1c8fb4aac48129bb65287d80e61c91c91fecc09455e0c749
\ No newline at end of file
4072a18085abe59d6df57ab0a8ed64bda2b53ed6318cdb20ca152dfcc6d973c4
\ No newline at end of file
harness/shots/baseline/darwin/pull-phone-dark.sha256+1−1
@@ -1 +1 @@
91e9b0ab3edc32e396e5e69277672f730923ebbd5a226f9b3c8e5205d3ff5a25
\ No newline at end of file
b41cf484a6c00073334832ad4076a61abf64d4875e140351e06ce8462a2cdfe6
\ No newline at end of file
harness/shots/baseline/darwin/pull-phone-light.sha256+1−1
@@ -1 +1 @@
91e9b0ab3edc32e396e5e69277672f730923ebbd5a226f9b3c8e5205d3ff5a25
\ No newline at end of file
b41cf484a6c00073334832ad4076a61abf64d4875e140351e06ce8462a2cdfe6
\ No newline at end of file
harness/shots/baseline/darwin/pulls-closed-desktop-dark.sha256+1−1
@@ -1 +1 @@
16aeaa767b22ffcbeba5cbccf458423a04544a9fa326ac22bb15539200de9b5d
\ No newline at end of file
db93e389bb6ef3a55407734cae432aebe5b32ad3d157ab900b9872944dcbefbe
\ No newline at end of file
harness/shots/baseline/darwin/pulls-closed-desktop-light.sha256+1−1
@@ -1 +1 @@
16aeaa767b22ffcbeba5cbccf458423a04544a9fa326ac22bb15539200de9b5d
\ No newline at end of file
db93e389bb6ef3a55407734cae432aebe5b32ad3d157ab900b9872944dcbefbe
\ No newline at end of file
harness/shots/baseline/darwin/pulls-closed-phone-dark.sha256+1−1
@@ -1 +1 @@
16aeaa767b22ffcbeba5cbccf458423a04544a9fa326ac22bb15539200de9b5d
\ No newline at end of file
db93e389bb6ef3a55407734cae432aebe5b32ad3d157ab900b9872944dcbefbe
\ No newline at end of file
harness/shots/baseline/darwin/pulls-closed-phone-light.sha256+1−1
@@ -1 +1 @@
16aeaa767b22ffcbeba5cbccf458423a04544a9fa326ac22bb15539200de9b5d
\ No newline at end of file
db93e389bb6ef3a55407734cae432aebe5b32ad3d157ab900b9872944dcbefbe
\ No newline at end of file
harness/shots/baseline/darwin/pulls-desktop-dark.sha256+1−1
@@ -1 +1 @@
beb590f1106cbd41c832c17e1a6f804fb0773208ecf57700da0a08a8b8d4f968
\ No newline at end of file
c73ac5d9056901d10797cadd80888b91857120e5afda6d55072922e0128aff4f
\ No newline at end of file
harness/shots/baseline/darwin/pulls-desktop-light.sha256+1−1
@@ -1 +1 @@
beb590f1106cbd41c832c17e1a6f804fb0773208ecf57700da0a08a8b8d4f968
\ No newline at end of file
c73ac5d9056901d10797cadd80888b91857120e5afda6d55072922e0128aff4f
\ No newline at end of file
harness/shots/baseline/darwin/pulls-phone-dark.sha256+1−1
@@ -1 +1 @@
beb590f1106cbd41c832c17e1a6f804fb0773208ecf57700da0a08a8b8d4f968
\ No newline at end of file
c73ac5d9056901d10797cadd80888b91857120e5afda6d55072922e0128aff4f
\ No newline at end of file
harness/shots/baseline/darwin/pulls-phone-light.sha256+1−1
@@ -1 +1 @@
beb590f1106cbd41c832c17e1a6f804fb0773208ecf57700da0a08a8b8d4f968
\ No newline at end of file
c73ac5d9056901d10797cadd80888b91857120e5afda6d55072922e0128aff4f
\ No newline at end of file
harness/shots/baseline/darwin/repository-desktop-dark.sha256+1−1
@@ -1 +1 @@
7dbe154de3fc058f87f86efe437e3445d0119a448944e34768291d30f0e4e46a
\ No newline at end of file
16f2992ccf96c83fd308ec0c5bfee04accef9e0a433ade4914035dcd7f5015d0
\ No newline at end of file
harness/shots/baseline/darwin/repository-desktop-light.sha256+1−1
@@ -1 +1 @@
7dbe154de3fc058f87f86efe437e3445d0119a448944e34768291d30f0e4e46a
\ No newline at end of file
16f2992ccf96c83fd308ec0c5bfee04accef9e0a433ade4914035dcd7f5015d0
\ No newline at end of file
harness/shots/baseline/darwin/repository-phone-dark.sha256+1−1
@@ -1 +1 @@
7dbe154de3fc058f87f86efe437e3445d0119a448944e34768291d30f0e4e46a
\ No newline at end of file
16f2992ccf96c83fd308ec0c5bfee04accef9e0a433ade4914035dcd7f5015d0
\ No newline at end of file
harness/shots/baseline/darwin/repository-phone-light.sha256+1−1
@@ -1 +1 @@
7dbe154de3fc058f87f86efe437e3445d0119a448944e34768291d30f0e4e46a
\ No newline at end of file
16f2992ccf96c83fd308ec0c5bfee04accef9e0a433ade4914035dcd7f5015d0
\ No newline at end of file
harness/shots/baseline/darwin/search-desktop-dark.sha256+1−1
@@ -1 +1 @@
813d05f01a8c8c233b11b6dfe7e7689954da78bbebb9bf3d519e18d9fe2a54c6
\ No newline at end of file
69c0c57f63a368fecf8cd98c91afd0813dc5fb8789c2080787aae425e8f461e2
\ No newline at end of file
harness/shots/baseline/darwin/search-desktop-light.sha256+1−1
@@ -1 +1 @@
813d05f01a8c8c233b11b6dfe7e7689954da78bbebb9bf3d519e18d9fe2a54c6
\ No newline at end of file
69c0c57f63a368fecf8cd98c91afd0813dc5fb8789c2080787aae425e8f461e2
\ No newline at end of file
harness/shots/baseline/darwin/search-phone-dark.sha256+1−1
@@ -1 +1 @@
813d05f01a8c8c233b11b6dfe7e7689954da78bbebb9bf3d519e18d9fe2a54c6
\ No newline at end of file
69c0c57f63a368fecf8cd98c91afd0813dc5fb8789c2080787aae425e8f461e2
\ No newline at end of file
harness/shots/baseline/darwin/search-phone-light.sha256+1−1
@@ -1 +1 @@
813d05f01a8c8c233b11b6dfe7e7689954da78bbebb9bf3d519e18d9fe2a54c6
\ No newline at end of file
69c0c57f63a368fecf8cd98c91afd0813dc5fb8789c2080787aae425e8f461e2
\ No newline at end of file
harness/shots/baseline/darwin/start-desktop-dark.png+0−0
A binary file, not shown.
harness/shots/baseline/darwin/start-desktop-dark.sha256+1−1
@@ -1 +1 @@
3f534347e2a4289729ecfa412b35b2dae2225d3953b5df52b9ede4981d2f41e0
\ No newline at end of file
84606eaa16b648b9da382d84f88fc845f892c1c442d754bf2a6cea498f00432e
\ No newline at end of file
harness/shots/baseline/darwin/start-desktop-light.png+0−0
A binary file, not shown.
harness/shots/baseline/darwin/start-desktop-light.sha256+1−1
@@ -1 +1 @@
3f534347e2a4289729ecfa412b35b2dae2225d3953b5df52b9ede4981d2f41e0
\ No newline at end of file
84606eaa16b648b9da382d84f88fc845f892c1c442d754bf2a6cea498f00432e
\ No newline at end of file
harness/shots/baseline/darwin/start-phone-dark.png+0−0
A binary file, not shown.
harness/shots/baseline/darwin/start-phone-dark.sha256+1−1
@@ -1 +1 @@
3f534347e2a4289729ecfa412b35b2dae2225d3953b5df52b9ede4981d2f41e0
\ No newline at end of file
84606eaa16b648b9da382d84f88fc845f892c1c442d754bf2a6cea498f00432e
\ No newline at end of file
harness/shots/baseline/darwin/start-phone-light.png+0−0
A binary file, not shown.
harness/shots/baseline/darwin/start-phone-light.sha256+1−1
@@ -1 +1 @@
3f534347e2a4289729ecfa412b35b2dae2225d3953b5df52b9ede4981d2f41e0
\ No newline at end of file
84606eaa16b648b9da382d84f88fc845f892c1c442d754bf2a6cea498f00432e
\ No newline at end of file
web/src/lib/data.ts+3−1
@@ -20,7 +20,9 @@ export async function data<T>(
path?: string,
missing = false
): Promise<T> {
const res = await fetch(path ?? `/_data${url.pathname}${url.search}`);
// Asked again each time, past an answer a browser kept from when answers
// at a commit hash were sent as immutable.
const res = await fetch(path ?? `/_data${url.pathname}${url.search}`, { cache: 'no-cache' });
if (res.redirected) {
const to = new URL(res.url);
redirect(307, `${to.pathname.replace(/^\/_data/, '')}${to.search}`);