← back to Contact Mailer Ideas
viewer: deep-link by batch slug not date (multiple batches per date now disambiguated); dropdown values switched to batch slugs
a514e3f615c292466e4154081b390b43b8deae78 · 2026-05-11 16:04:51 -0700 · Steve Abrams
Files touched
Diff
commit a514e3f615c292466e4154081b390b43b8deae78
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon May 11 16:04:51 2026 -0700
viewer: deep-link by batch slug not date (multiple batches per date now disambiguated); dropdown values switched to batch slugs
---
viewer/server.js | 39 ++++++++++++++++++++++++++++++---------
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/viewer/server.js b/viewer/server.js
index 37986ec..8c0df66 100644
--- a/viewer/server.js
+++ b/viewer/server.js
@@ -66,9 +66,12 @@ function listBatches() {
return batches;
}
-function loadBatch(date) {
+function loadBatch(dateOrBatch) {
const batches = listBatches();
- let target = batches.find(b => b.date === date) || batches[0];
+ // Match by batch slug first (more specific when multiple batches share a date), then by date
+ let target = batches.find(b => b.batch === dateOrBatch)
+ || batches.find(b => b.date === dateOrBatch)
+ || batches[0];
if (!target) return { meta: {}, byIdx: {}, allTicks: [], batches: [] };
const doc = JSON.parse(fs.readFileSync(path.join(BATCHES_DIR, target.file), 'utf8'));
const ideas = doc.ideas || [];
@@ -107,8 +110,8 @@ function loadIdeas() {
}
app.get('/api/state', (req, res) => {
- const date = req.query.date;
- const data = date ? loadBatch(date) : loadIdeas();
+ const selector = req.query.batch || req.query.date;
+ const data = selector ? loadBatch(selector) : loadIdeas();
data.notes = readNotes()[data.selected && data.selected.batch] || {};
res.json(data);
});
@@ -326,7 +329,9 @@ footer{padding:20px 48px 40px;color:#5a5a62;font-size:12px;text-align:center}
<footer>port 9773 · localhost only · source ~/.claude/skills/idea-loop/data/ideas.jsonl</footer>
<script>
const COLORS = ${JSON.stringify(COLORS)};
-let currentDate = null;
+// Parse URL params for deep-link to a specific batch or date
+const _urlParams = new URLSearchParams(window.location.search);
+let currentDate = _urlParams.get('batch') || _urlParams.get('date') || null;
let state = null;
const LS = window.localStorage;
const q = document.getElementById('q');
@@ -371,10 +376,26 @@ density.addEventListener('input', () => {
async function loadBatches(){
const r = await fetch('/api/batches'); const list = await r.json();
const sel = document.getElementById('batchSel');
- sel.innerHTML = list.map(b => '<option value="'+b.date+'">'+b.date+' · '+b.count+' ideas'+(b.generator!=='manual'?' (auto)':'')+'</option>').join('');
- if (!currentDate && list.length) currentDate = list[0].date;
+ // Use batch slug as the value (unique) instead of date (which can collide)
+ sel.innerHTML = list.map(b => '<option value="'+b.batch+'">'+b.date+' · '+b.batch+' · '+b.count+' ideas'+(b.generator && b.generator!=='manual'?' (auto)':'')+'</option>').join('');
+ // Map currentDate to a matching batch if user passed a date
+ if (currentDate) {
+ const direct = list.find(b => b.batch === currentDate);
+ if (!direct) {
+ const byDate = list.find(b => b.date === currentDate);
+ if (byDate) currentDate = byDate.batch;
+ }
+ }
+ if (!currentDate && list.length) currentDate = list[0].batch;
sel.value = currentDate || '';
- sel.onchange = () => { currentDate = sel.value; load(); };
+ sel.onchange = () => {
+ currentDate = sel.value;
+ // Update URL so it's deep-linkable
+ const u = new URL(window.location);
+ u.searchParams.set('batch', currentDate);
+ window.history.replaceState({}, '', u);
+ load();
+ };
renderBanner(list);
}
function renderBanner(list){
@@ -395,7 +416,7 @@ function renderBanner(list){
}
let stateSig = '';
async function load(){
- const url = currentDate ? '/api/state?date='+encodeURIComponent(currentDate) : '/api/state';
+ const url = currentDate ? '/api/state?batch='+encodeURIComponent(currentDate) : '/api/state';
const r = await fetch(url); const j = await r.json();
// Compare a cheap signature so background refreshes don't disturb DOM/scroll when nothing changed
const sig = JSON.stringify({
← a8c0f7d combos #7 Spectrum (36/40) — productize age-adaptive-theme s
·
back to Contact Mailer Ideas
·
viewer: dedicated renderers for SWOT (5 colored tiles + comp 008d6db →