Skip to content

Commit 759b829

Browse files
vishrclaude
andcommitted
feat(docs): dynamic version badge + command-palette search empty state
- Hero version badge pulled at build time (latest echo/v5 via Go module proxy, with fallback) instead of hardcoded v5.2 — refreshes via the daily cron. - Replace the empty Pagefind search modal with a command-palette launchpad (Start here / Popular quick links + shortcut footer); shown only while the query is empty, hidden once results appear. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 49ae2db commit 759b829

5 files changed

Lines changed: 93 additions & 2 deletions

File tree

site/astro.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default defineConfig({
2929
components: {
3030
Footer: './src/components/Footer.astro',
3131
PageTitle: './src/components/PageTitle.astro',
32+
Search: './src/components/Search.astro',
3233
},
3334
head: [
3435
// Google Analytics (carried over from the Docusaurus site, anonymized IP).

site/src/components/HomeHero.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
// Living Terminal hero: code window + a terminal pane that types `curl`
33
// and streams Echo's JSON response. Animation is client-side, with a
44
// static final-state fallback for reduced-motion / no-JS.
5-
import { starsLabel } from '../data/github.ts';
5+
import { starsLabel, echoVersion } from '../data/github.ts';
66
---
77

88
<section class="hh">
99
<div class="hh-left">
10-
<span class="hh-eyebrow"><i class="ph ph-sparkle"></i> Echo v5.2 — now released</span>
10+
<span class="hh-eyebrow"><i class="ph ph-sparkle"></i> Echo {echoVersion} — now released</span>
1111
<h1>Build fast Go APIs.<br /><span class="g">Without the bloat.</span></h1>
1212
<p class="hh-sub">
1313
A high-performance, minimalist Go web framework — a zero-allocation

site/src/components/Search.astro

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
import Default from '@astrojs/starlight/components/Search.astro';
3+
---
4+
<Default />
5+
6+
<script>
7+
// Command-palette empty state: inject quick links + a shortcut footer into the
8+
// Pagefind modal once it mounts. terminal.css shows it only while the query is
9+
// empty (the results drawer carries .pagefind-ui__hidden then).
10+
const PANEL = `
11+
<div class="echo-search-empty">
12+
<div class="ess-group">
13+
<div class="ess-label">Start here</div>
14+
<a class="ess-link" href="/guide/quickstart/"><i class="ph ph-rocket-launch"></i> Quickstart <span class="ess-sec">Guide</span></a>
15+
<a class="ess-link" href="/guide/routing/"><i class="ph ph-signpost"></i> Routing <span class="ess-sec">Guide</span></a>
16+
<a class="ess-link" href="/guide/binding/"><i class="ph ph-brackets-curly"></i> Binding <span class="ess-sec">Guide</span></a>
17+
</div>
18+
<div class="ess-group">
19+
<div class="ess-label">Popular</div>
20+
<a class="ess-link" href="/middleware/jwt/"><i class="ph ph-lock-key"></i> JWT <span class="ess-sec">Middleware</span></a>
21+
<a class="ess-link" href="/middleware/cors/"><i class="ph ph-globe"></i> CORS <span class="ess-sec">Middleware</span></a>
22+
<a class="ess-link" href="/cookbook/hello-world/"><i class="ph ph-cube"></i> Hello World <span class="ess-sec">Cookbook</span></a>
23+
</div>
24+
<div class="ess-foot">
25+
<span><kbd>↵</kbd>open</span><span><kbd>↑</kbd><kbd>↓</kbd>navigate</span><span><kbd>esc</kbd>close</span>
26+
</div>
27+
</div>`;
28+
29+
function inject() {
30+
const ui = document.querySelector('.pagefind-ui');
31+
if (!ui || ui.querySelector('.echo-search-empty')) return !!ui;
32+
const form = ui.querySelector('.pagefind-ui__form');
33+
if (!form) return false;
34+
form.insertAdjacentHTML('afterend', PANEL);
35+
return true;
36+
}
37+
38+
// Pagefind mounts lazily when the dialog first opens — watch for it, then stop.
39+
if (!inject()) {
40+
const obs = new MutationObserver(() => { if (inject()) obs.disconnect(); });
41+
obs.observe(document.body, { childList: true, subtree: true });
42+
}
43+
</script>

site/src/data/github.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,22 @@ export const stars = await fetchStars();
2929

3030
/** e.g. 32412 -> "32.4k" */
3131
export const starsLabel = stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : String(stars);
32+
33+
const FALLBACK_VERSION = 'v5';
34+
35+
// Latest released echo/v5, via the Go module proxy — canonical and v5-only
36+
// (avoids GitHub "latest release" occasionally pointing at a v4 patch).
37+
async function fetchLatestVersion(): Promise<string> {
38+
try {
39+
const res = await fetch('https://proxy.golang.org/github.com/labstack/echo/v5/@latest');
40+
if (!res.ok) throw new Error(`Go proxy responded ${res.status}`);
41+
const data = await res.json();
42+
return typeof data.Version === 'string' ? data.Version : FALLBACK_VERSION;
43+
} catch (e) {
44+
console.warn(`[github] version fetch failed; using fallback ${FALLBACK_VERSION}:`, e);
45+
return FALLBACK_VERSION;
46+
}
47+
}
48+
49+
/** e.g. "v5.2.1" */
50+
export const echoVersion = await fetchLatestVersion();

site/src/styles/terminal.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,34 @@
8787
/* search box (chrome) */
8888
site-search button { border-radius: 8px !important; }
8989

90+
/* Empty search modal: a command-palette launchpad (quick links + shortcut
91+
footer) injected by Search.astro, shown only before a query exists. Pagefind
92+
marks the results drawer .pagefind-ui__hidden when empty. */
93+
.echo-search-empty { display: none; }
94+
.pagefind-ui:has(.pagefind-ui__drawer.pagefind-ui__hidden) .echo-search-empty { display: block; }
95+
.echo-search-empty { margin-top: 16px; }
96+
.ess-group + .ess-group { margin-top: 14px; }
97+
.ess-label {
98+
font-family: var(--sl-font-mono); font-size: 0.66rem; letter-spacing: 0.12em;
99+
text-transform: uppercase; color: var(--sl-color-gray-4); padding: 0 4px 6px;
100+
}
101+
.ess-link {
102+
display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: 9px;
103+
text-decoration: none; color: var(--sl-color-white); font-size: 0.9rem; line-height: 1;
104+
}
105+
.ess-link i { font-size: 1.05rem; color: var(--echo-cyan-text); width: 1.2em; text-align: center; }
106+
.ess-link .ess-sec { margin-left: auto; font-family: var(--sl-font-mono); font-size: 0.7rem; color: var(--sl-color-gray-4); }
107+
.ess-link:hover, .ess-link:focus-visible { background: var(--echo-soft); outline: none; }
108+
.ess-foot {
109+
display: flex; gap: 18px; justify-content: center; flex-wrap: wrap;
110+
margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--sl-color-hairline);
111+
font-family: var(--sl-font-mono); font-size: 0.72rem; color: var(--sl-color-gray-4);
112+
}
113+
.ess-foot kbd {
114+
font-family: var(--sl-font-mono); font-size: 0.72rem; background: var(--sl-color-bg-inline-code);
115+
border: 1px solid var(--sl-color-hairline); border-radius: 5px; padding: 1px 6px; margin-right: 5px;
116+
}
117+
90118
/* code blocks — let Expressive Code round the whole frame as one unit
91119
(title bar: rounded top, code body: rounded bottom). Don't force the inner
92120
<pre> corners or it detaches from the title bar into a second box. */

0 commit comments

Comments
 (0)