diff --git a/html/live/index.html b/html/live/index.html
index d48ee17..83d9e74 100644
--- a/html/live/index.html
+++ b/html/live/index.html
@@ -403,8 +403,10 @@ function renderTeamBar(stats) {
// Clear existing member pills (keep the "Everyone" button)
const allBtn = bar.querySelector('[data-member="all"]');
bar.innerHTML = '';
- if (activeMember === 'all') allBtn.classList.add('active'); else allBtn.classList.remove('active');
- bar.appendChild(allBtn);
+ if (allBtn) {
+ if (activeMember === 'all') allBtn.classList.add('active'); else allBtn.classList.remove('active');
+ bar.appendChild(allBtn);
+ }
stats.members.forEach(m => {
const btn = document.createElement('button');
@@ -419,7 +421,7 @@ function renderTeamBar(stats) {
function fmtDate(str){try{const d=new Date(str+'T00:00:00');return d.toLocaleDateString('en-GB',{weekday:'short',day:'numeric',month:'short',year:'numeric'});}catch{return str;}}
function esc(s){const d=document.createElement('div');d.textContent=s;return d.innerHTML;}
-function anim(el,target,dur){if(!el)return;const t0=performance.now();(function f(now){const p=Math.min((now-t0)/dur,1);el.textContent=Math.floor(target*(1-Math.pow(1-p,3)));if(p<1)requestAnimationFrame(f);})(t0);}
+function anim(el,target,dur){if(!el)return;const t0=performance.now();(function f(now){const p=Math.min((now-t0)/dur,1);el.textContent=p>=1?target:Math.floor(target*(1-Math.pow(1-p,3)));if(p<1)requestAnimationFrame(f);})(t0);}
document.querySelector('.lv-pill[data-filter="all"]').onclick=()=>filterTo('all');
init();
diff --git a/server.js b/server.js
index 1508e57..9ee722b 100644
--- a/server.js
+++ b/server.js
@@ -233,12 +233,26 @@ app.get('/work/', (req, res) => res.redirect(301, '/work/charityright/'));
// Serve static files from html/ directory
app.use(express.static(path.join(__dirname, 'html')));
+// API 404 — don't let SPA fallback swallow bad API routes
+app.all('/api/*', (req, res) => {
+ res.status(404).json({ error: 'not found' });
+});
+
// SPA fallback: send index.html for unmatched routes
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'html', 'index.html'));
});
const PORT = process.env.PORT || 3000;
-app.listen(PORT, '0.0.0.0', () => {
+const server = app.listen(PORT, '0.0.0.0', () => {
console.log(`QuikCue Site server listening on :${PORT}`);
});
+
+// Graceful shutdown
+process.on('SIGTERM', () => {
+ console.log('SIGTERM received, shutting down...');
+ server.close(() => {
+ if (pool) pool.end();
+ process.exit(0);
+ });
+});