← back to Norma Platform
IG /spoonflower: server-inject data into the page so it renders without an authed XHR
1e26b119125047d1e229160b3966047fa95111c7 · 2026-08-17 09:14:22 -0700 · Steve Abrams
Chrome strips URL-embedded basic-auth creds, so fetch('/api/spoonflower') 401'd and
the board showed empty. Now the route injects the JSON into #sf-data and the page
first-paints from that; the XHR is refresh-only and fails silently.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M agents/instagram-agent/public/spoonflower-viewer.htmlM agents/instagram-agent/spoonflower-api.js
Diff
commit 1e26b119125047d1e229160b3966047fa95111c7
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 17 09:14:22 2026 -0700
IG /spoonflower: server-inject data into the page so it renders without an authed XHR
Chrome strips URL-embedded basic-auth creds, so fetch('/api/spoonflower') 401'd and
the board showed empty. Now the route injects the JSON into #sf-data and the page
first-paints from that; the XHR is refresh-only and fails silently.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
agents/instagram-agent/public/spoonflower-viewer.html | 13 ++++++++++---
agents/instagram-agent/spoonflower-api.js | 7 ++++++-
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/agents/instagram-agent/public/spoonflower-viewer.html b/agents/instagram-agent/public/spoonflower-viewer.html
index ffafb01..14029d5 100644
--- a/agents/instagram-agent/public/spoonflower-viewer.html
+++ b/agents/instagram-agent/public/spoonflower-viewer.html
@@ -48,11 +48,15 @@
<div class="grid" id="grid"></div>
<div class="note" id="note"></div>
</main>
+<script id="sf-data" type="application/json">/*__SPOONFLOWER_JSON__*/</script>
<script>
const esc = (s) => (s||'').replace(/[&<>"]/g, c => ({'&':'&','<':'<','>':'>','"':'"'}[c]));
const hi = (s) => esc(s).replace(/(spoonflower)/ig, '<b>$1</b>');
-async function load() {
- const r = await fetch('/api/spoonflower'); const d = await r.json();
+// Server injects the data into #sf-data so the board renders even if the authed
+// XHR is blocked (Chrome strips URL creds → /api/spoonflower 401). XHR is refresh-only.
+function injected() { try { return JSON.parse(document.getElementById('sf-data').textContent); } catch { return null; } }
+function render(d) {
+ if (!d || !d.posts) return;
const stats = document.getElementById('stats');
stats.innerHTML =
`<span class="pill">Total flagged <b>${d.total}</b></span>` +
@@ -76,7 +80,10 @@ async function load() {
'<b>hashtag</b> = a genuine 2022 repost where #spoonflowerwallpaper is 1 of 16 tags (Steve chose: delete it too). ' +
'Deletion needs the openclaw Chrome logged in as each owning account, then runs serialized + verified.';
}
-load(); setInterval(load, 15000);
+async function refresh() { try { const r = await fetch('/api/spoonflower'); if (r.ok) render(await r.json()); } catch {} }
+render(injected()); // first paint from server-injected data (no auth needed)
+refresh(); // then try a live refresh (silently ignored if XHR is 401)
+setInterval(refresh, 15000);
</script>
</body>
</html>
diff --git a/agents/instagram-agent/spoonflower-api.js b/agents/instagram-agent/spoonflower-api.js
index f207d83..0192494 100644
--- a/agents/instagram-agent/spoonflower-api.js
+++ b/agents/instagram-agent/spoonflower-api.js
@@ -54,7 +54,12 @@ function getSpoonflower() {
function registerSpoonflowerRoutes(app) {
app.get('/spoonflower', (req, res) => {
if (!fs.existsSync(VIEWER)) return res.status(404).send('spoonflower-viewer.html missing');
- res.type('html').send(fs.readFileSync(VIEWER, 'utf8'));
+ // Inject the data straight into the page so it renders without a separate authed XHR
+ // (browsers strip URL creds → /api/spoonflower 401 → empty board).
+ let html = fs.readFileSync(VIEWER, 'utf8');
+ const json = JSON.stringify(getSpoonflower()).replace(/</g, '\\u003c');
+ html = html.replace('/*__SPOONFLOWER_JSON__*/', json);
+ res.type('html').send(html);
});
app.get('/api/spoonflower', (req, res) => {
try { res.json(getSpoonflower()); } catch (e) { res.status(500).json({ error: e.message }); }
← c573cf5 IG: add /spoonflower purge viewer (thumbnails + live delete-
·
back to Norma Platform
·
Harden IG delete-originals.js: retry stale refs, recover dea 04b7ade →