From 16003ee39f50ee7ec729acebe9f2ea388b1d2f53 Mon Sep 17 00:00:00 2001
From: Eric Wagoner
Date: Sun, 2 Aug 2026 17:37:48 -0400
Subject: [PATCH] Web pages re-render only when their data changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The newer pages rebuilt innerHTML on every poll, which re-renders every
(the visible blink on Photos) and wiped the pipeline page's limit
field between polls. Every page now snapshots its payload and skips
identical renders — the guard the review page always had.
Co-Authored-By: Claude Fable 5
---
src/bggpipe/templates/pages/catalog.html | 4 ++++
src/bggpipe/templates/pages/library.html | 7 ++++++-
src/bggpipe/templates/pages/photos.html | 5 +++++
src/bggpipe/templates/pages/pipeline.html | 7 ++++++-
src/bggpipe/templates/pages/queue.html | 7 ++++++-
5 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/src/bggpipe/templates/pages/catalog.html b/src/bggpipe/templates/pages/catalog.html
index 929af89..46f8778 100644
--- a/src/bggpipe/templates/pages/catalog.html
+++ b/src/bggpipe/templates/pages/catalog.html
@@ -39,8 +39,12 @@ function render() {
: `Nothing extracted yet — start on the photos page.`}
`;
}
+let LAST = null;
async function refresh() {
const state = await fetchJSON("/api/state");
+ const payload = JSON.stringify(state.catalog);
+ if (payload === LAST) return;
+ LAST = payload;
CATALOG = state.catalog;
render();
}
diff --git a/src/bggpipe/templates/pages/library.html b/src/bggpipe/templates/pages/library.html
index dee19df..45135be 100644
--- a/src/bggpipe/templates/pages/library.html
+++ b/src/bggpipe/templates/pages/library.html
@@ -45,8 +45,13 @@ function render() {
Run the pipeline through enrich to fill these shelves.`}`;
}
+let LAST = null;
async function refresh() {
- GAMES = await fetchJSON("/api/library");
+ const games = await fetchJSON("/api/library");
+ const payload = JSON.stringify(games);
+ if (payload === LAST) return;
+ LAST = payload;
+ GAMES = games;
render();
}
diff --git a/src/bggpipe/templates/pages/photos.html b/src/bggpipe/templates/pages/photos.html
index 4957017..ec5c530 100644
--- a/src/bggpipe/templates/pages/photos.html
+++ b/src/bggpipe/templates/pages/photos.html
@@ -59,11 +59,16 @@ function render(state, photos) {
`).join("");
}
+let LAST = null;
async function refresh() {
const [state, photos] = await Promise.all([
fetchJSON("/api/state"),
fetchJSON("/api/photos-list"),
]);
+ // re-render only on change: rebuilding innerHTML re-renders every
+ const payload = JSON.stringify([state.unidentified, state.warnings, photos]);
+ if (payload === LAST) return;
+ LAST = payload;
render(state, photos);
}
diff --git a/src/bggpipe/templates/pages/pipeline.html b/src/bggpipe/templates/pages/pipeline.html
index bf5b59d..3f7f07f 100644
--- a/src/bggpipe/templates/pages/pipeline.html
+++ b/src/bggpipe/templates/pages/pipeline.html
@@ -78,8 +78,13 @@ function render() {
if (atBottom) logEl.scrollTop = logEl.scrollHeight;
}
+let LAST = null;
async function refresh() {
- P = await fetchJSON("/api/pipeline");
+ const p = await fetchJSON("/api/pipeline");
+ const payload = JSON.stringify(p);
+ if (payload === LAST) return;
+ LAST = payload;
+ P = p;
render();
}
diff --git a/src/bggpipe/templates/pages/queue.html b/src/bggpipe/templates/pages/queue.html
index f5453e9..8cd5df2 100644
--- a/src/bggpipe/templates/pages/queue.html
+++ b/src/bggpipe/templates/pages/queue.html
@@ -43,8 +43,13 @@ function render(q) {
document.getElementById("queuebody").innerHTML = html;
}
+let LAST = null;
async function refresh() {
- render(await fetchJSON("/api/queue"));
+ const q = await fetchJSON("/api/queue");
+ const payload = JSON.stringify(q);
+ if (payload === LAST) return;
+ LAST = payload;
+ render(q);
}
refresh().catch(err => errorBanner(err.message || err));