search for standard sites pub-search.waow.tech
search zig blog atproto

fix: stats links use same origin, move theme toggle to footer

- stats/dashboard links use /dashboard.html (same origin) instead of
going through backend redirect to dead leaflet-search.pages.dev URL
- theme toggle moved from cramped header to bottom of page where it
doesn't clutter the title line
- dashboard "back" and title links use relative paths (same origin)
- backend DASHBOARD_URL default updated to pub-search.waow.tech
- localStorage theme now shared between search and stats pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+7 -9
+1 -1
backend/src/server.zig
··· 438 } 439 440 fn getDashboardUrl() []const u8 { 441 - return std.posix.getenv("DASHBOARD_URL") orelse "https://leaflet-search.pages.dev/dashboard.html"; 442 } 443 444 fn handleDashboard(request: *http.Server.Request) !void {
··· 438 } 439 440 fn getDashboardUrl() []const u8 { 441 + return std.posix.getenv("DASHBOARD_URL") orelse "https://pub-search.waow.tech/dashboard.html"; 442 } 443 444 fn handleDashboard(request: *http.Server.Request) !void {
-1
site/dashboard.css
··· 231 .theme-toggle { 232 display: inline-flex; 233 gap: 0.25rem; 234 - margin-left: 0.5rem; 235 } 236 237 .theme-option {
··· 231 .theme-toggle { 232 display: inline-flex; 233 gap: 0.25rem; 234 } 235 236 .theme-option {
+2 -2
site/dashboard.html
··· 16 </head> 17 <body> 18 <div class="container"> 19 - <h1><a href="https://pub-search.waow.tech" class="title">pub search</a> <span class="dim">/ stats</span> <span class="theme-toggle" id="theme-toggle"></span></h1> 20 21 <section> 22 <div class="metrics"> ··· 85 </section> 86 87 <footer> 88 - <a href="https://pub-search.waow.tech">back</a> · source on <a href="https://tangled.sh/@zzstoatzz.io/leaflet-search">tangled</a> 89 </footer> 90 </div> 91
··· 16 </head> 17 <body> 18 <div class="container"> 19 + <h1><a href="/" class="title">pub search</a> <span class="dim">/ stats</span></h1> 20 21 <section> 22 <div class="metrics"> ··· 85 </section> 86 87 <footer> 88 + <a href="/">back</a> · source on <a href="https://tangled.sh/@zzstoatzz.io/leaflet-search">tangled</a> · <span class="theme-toggle" id="theme-toggle"></span> 89 </footer> 90 </div> 91
+4 -5
site/index.html
··· 617 .theme-toggle { 618 display: inline-flex; 619 gap: 0.25rem; 620 - margin-left: 0.5rem; 621 } 622 623 .theme-option { ··· 765 </head> 766 <body> 767 <div class="container"> 768 - <h1><a href="/" class="title">pub search</a> <span class="by">by <a href="https://bsky.app/profile/zzstoatzz.io" target="_blank">@zzstoatzz.io</a></span> <a href="https://tangled.sh/@zzstoatzz.io/leaflet-search" target="_blank" class="src">[src]</a> <a id="header-stats" class="stats-link"></a> <span class="theme-toggle" id="theme-toggle"></span></h1> 769 770 <div class="search-box"> 771 <input type="text" id="query" placeholder="search content..." autofocus> ··· 792 </div> 793 794 <div id="stats" class="stats"></div> 795 </div> 796 797 <script> ··· 1533 fetch(`${API_URL}/stats`) 1534 .then(r => r.json()) 1535 .then(data => { 1536 - statsDiv.innerHTML = `${data.documents} documents, ${data.publications} publications · <a href="${API_URL}/dashboard" target="_blank">stats</a>`; 1537 const headerStats = document.getElementById('header-stats'); 1538 - headerStats.href = `${API_URL}/dashboard`; 1539 - headerStats.target = '_blank'; 1540 headerStats.textContent = `[${data.documents.toLocaleString()} docs]`; 1541 }) 1542 .catch(() => {
··· 617 .theme-toggle { 618 display: inline-flex; 619 gap: 0.25rem; 620 } 621 622 .theme-option { ··· 764 </head> 765 <body> 766 <div class="container"> 767 + <h1><a href="/" class="title">pub search</a> <span class="by">by <a href="https://bsky.app/profile/zzstoatzz.io" target="_blank">@zzstoatzz.io</a></span> <a href="https://tangled.sh/@zzstoatzz.io/leaflet-search" target="_blank" class="src">[src]</a> <a id="header-stats" class="stats-link"></a></h1> 768 769 <div class="search-box"> 770 <input type="text" id="query" placeholder="search content..." autofocus> ··· 791 </div> 792 793 <div id="stats" class="stats"></div> 794 + <div class="stats" style="margin-top:0.5rem"><span class="theme-toggle" id="theme-toggle"></span></div> 795 </div> 796 797 <script> ··· 1533 fetch(`${API_URL}/stats`) 1534 .then(r => r.json()) 1535 .then(data => { 1536 + statsDiv.innerHTML = `${data.documents} documents, ${data.publications} publications · <a href="/dashboard.html">stats</a>`; 1537 const headerStats = document.getElementById('header-stats'); 1538 + headerStats.href = '/dashboard.html'; 1539 headerStats.textContent = `[${data.documents.toLocaleString()} docs]`; 1540 }) 1541 .catch(() => {