← back to Claude Webdev Accelerator
templates/public/index.html
56 lines
<!doctype html><html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1"><title>Storefront starter</title>
<style>
:root{--cols:4}
*{box-sizing:border-box} body{margin:0;font:15px/1.4 -apple-system,Segoe UI,Roboto,sans-serif;color:#1a1a1a;background:#fafafa}
header{display:flex;gap:14px;align-items:center;flex-wrap:wrap;padding:14px 20px;border-bottom:1px solid #e6e6e6;position:sticky;top:0;background:#fff;z-index:5}
h1{font-size:17px;margin:0;font-weight:700} .spacer{flex:1}
label{font-size:12px;color:#666;display:flex;gap:6px;align-items:center}
select,input[type=range]{font:inherit} .count{font-size:12px;color:#999}
.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:14px;padding:20px}
.card{background:#fff;border:1px solid #e6e6e6;border-radius:8px;overflow:hidden}
.card img{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;background:#f0f0f0}
.meta{padding:8px 10px} .t{font-size:13px;font-weight:600;margin:0 0 2px} .s{font-size:11px;color:#888}
.p{font-size:13px;margin-top:4px} .empty{padding:40px;color:#999;text-align:center}
</style></head><body>
<header>
<h1>Storefront starter</h1>
<label>Sort
<select id="sort">
<option value="newest">Newest</option>
<option value="title">Title A→Z</option>
<option value="sku">SKU A→Z</option>
<option value="price-asc">Price ↑</option>
<option value="price-desc">Price ↓</option>
<option value="light">Light → Dark</option>
<option value="dark">Dark → Light</option>
</select>
</label>
<label>Density <input id="density" type="range" min="2" max="8" value="4"></label>
<span class="spacer"></span><span class="count" id="count"></span>
</header>
<div class="grid" id="grid"><div class="empty">Loading…</div></div>
<script>
// House rule: sort + density both persist in localStorage so the choice survives reloads.
const $=s=>document.querySelector(s), esc=s=>(s||'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));
const sortSel=$('#sort'), dens=$('#density');
sortSel.value=localStorage.getItem('sort')||'newest'; dens.value=localStorage.getItem('cols')||'4';
function applyCols(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem('cols',dens.value);}
applyCols();
async function load(){
const r=await fetch('/api/products?sort='+encodeURIComponent(sortSel.value)); const d=await r.json();
$('#count').textContent=d.count+' items';
$('#grid').innerHTML = d.products.length ? d.products.map(p=>`
<div class="card">
<img src="${esc(p.image||'')}" alt="${esc(p.title||'')}" loading="lazy">
<div class="meta"><p class="t">${esc(p.title||'Untitled')}</p>
<div class="s">${esc(p.sku||p.handle||'')}</div>
${p.price?`<div class="p">$${Number(p.price).toFixed(2)}</div>`:''}
</div>
</div>`).join('') : '<div class="empty">No products yet — fill data/products.json.</div>';
}
sortSel.onchange=()=>{localStorage.setItem('sort',sortSel.value);load();};
dens.oninput=applyCols;
load();
</script></body></html>