diff --git a/CLAUDE.md b/CLAUDE.md index e5bd7af..1d9bb8f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,6 +59,19 @@ Required in `.env`: ## Website - **Domain**: lukeattheroost.com (behind Cloudflare) - **Analytics**: Cloudflare Web Analytics (enable in Cloudflare dashboard, no code changes needed) +- **Deploy**: `npx wrangler pages deploy website/ --project-name=lukeattheroost --branch=main` + +## Git Push +- If `mmgnas` times out, use the 10g hostname: + ```bash + GIT_SSH_COMMAND="ssh -o HostName=mmgnas-10g -p 2222 -i ~/.ssh/gitea_mmgnas" git push origin main + ``` + +## Hetzner VPS (Mail Server) +- **IP**: `46.225.164.41` +- **SSH**: `ssh root@46.225.164.41` (uses default key `~/.ssh/id_rsa`) +- **Mail**: `docker-mailserver` at `/opt/mailserver/` +- **Manage accounts**: `docker exec mailserver setup email add/del/list` ## Episodes Published - Episode 6 published 2026-02-08 (podcast6.mp3, ~31 min) diff --git a/backend/main.py b/backend/main.py index 589ecbe..6c88179 100644 --- a/backend/main.py +++ b/backend/main.py @@ -4215,7 +4215,36 @@ async def set_music_volume(request: MusicRequest): # --- Sound Effects Endpoints --- SFX_DISPLAY_NAMES = { - "cheer": "correct", + "airhorn": "📢 Airhorn", + "applause": "👏 Applause", + "boo": "👎 Boo", + "busy": "📞 Busy", + "buzzer": "🚫 Buzzer", + "car_crash": "💥 Car Crash", + "cheer": "✅ Correct", + "clock_ticking": "⏰ Clock Ticking", + "commercial_jingle": "🎵 Jingle", + "crickets": "🦗 Crickets", + "ding": "🔔 Ding", + "doorbell": "🚪 Doorbell", + "drumroll": "🥁 Drumroll", + "dun_dun_dun": "😱 Dun Dun Dun", + "explosion": "💣 Explosion", + "fart": "💨 Fart", + "gasp": "😮 Gasp", + "glass_shatter": "🪟 Glass Shatter", + "hangup": "📵 Hangup", + "hold_music": "🎶 Hold Music", + "laugh_track": "😂 Laugh Track", + "news_stinger": "📰 News Stinger", + "phone_ring": "☎️ Phone Ring", + "record_scratch": "💿 Record Scratch", + "rimshot": "🪘 Rimshot", + "sad_trombone": "😢 Sad Trombone", + "thunder": "⛈️ Thunder", + "victory_fanfare": "🏆 Victory Fanfare", + "whoosh": "🌀 Whoosh", + "wolf_whistle": "😏 Wolf Whistle", } SFX_PRIORITY = ["sad_trombone", "cheer"] diff --git a/frontend/css/style.css b/frontend/css/style.css index 8bdffff..4e1afaf 100644 --- a/frontend/css/style.css +++ b/frontend/css/style.css @@ -771,3 +771,4 @@ section h2 { .email-subject { font-size: 0.85rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .email-preview { font-size: 0.8rem; color: var(--text-muted); line-height: 1.3; } .email-item .vm-actions { margin-top: 0.25rem; } +.email-body-expanded { margin-top: 0.4rem; padding: 0.5rem; background: rgba(232, 121, 29, 0.08); border-radius: var(--radius-sm); font-size: 0.85rem; line-height: 1.5; white-space: pre-wrap; max-height: 200px; overflow-y: auto; } diff --git a/frontend/js/app.js b/frontend/js/app.js index 0bee1bc..4bdb89a 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -1418,10 +1418,17 @@ function escapeHtml(str) { } function viewEmail(id) { + const item = document.querySelector(`.email-item[data-id="${id}"]`); + if (!item) return; + const existing = item.querySelector('.email-body-expanded'); + if (existing) { existing.remove(); return; } fetch('/api/emails').then(r => r.json()).then(emails => { const em = emails.find(e => e.id === id); if (!em) return; - alert(`From: ${em.sender}\nSubject: ${em.subject}\n\n${em.body}`); + const div = document.createElement('div'); + div.className = 'email-body-expanded'; + div.textContent = em.body; + item.appendChild(div); }); }