Add live GitHub star count to stats page
This commit is contained in:
@@ -37,6 +37,17 @@ const headerLinks = [
|
|||||||
{ href: "#token-cost", label: "Token Cost" },
|
{ href: "#token-cost", label: "Token Cost" },
|
||||||
{ href: "#session-cost", label: "Session Cost" },
|
{ href: "#session-cost", label: "Session Cost" },
|
||||||
] as const
|
] as const
|
||||||
|
const githubLink = {
|
||||||
|
href: "https://github.com/anomalyco/opencode",
|
||||||
|
apiHref: "https://api.github.com/repos/anomalyco/opencode",
|
||||||
|
label: "GitHub",
|
||||||
|
fallbackStars: "150K",
|
||||||
|
ariaLabel: "Star OpenCode on GitHub",
|
||||||
|
}
|
||||||
|
const compactNumberFormatter = new Intl.NumberFormat("en", {
|
||||||
|
notation: "compact",
|
||||||
|
maximumFractionDigits: 1,
|
||||||
|
})
|
||||||
const usageColors = [
|
const usageColors = [
|
||||||
"#ed6aff",
|
"#ed6aff",
|
||||||
"#a684ff",
|
"#a684ff",
|
||||||
@@ -61,12 +72,30 @@ const getData = query(async () => {
|
|||||||
return runtime.runPromise(getStatsHomeData())
|
return runtime.runPromise(getStatsHomeData())
|
||||||
}, "getStatsHomeData")
|
}, "getStatsHomeData")
|
||||||
|
|
||||||
|
const getGitHubStars = query(async () => {
|
||||||
|
"use server"
|
||||||
|
return fetch(githubLink.apiHref, {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/vnd.github+json",
|
||||||
|
"X-GitHub-Api-Version": "2022-11-28",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => (response.ok ? response.json() : undefined))
|
||||||
|
.then((body: unknown) =>
|
||||||
|
body && typeof body === "object" && "stargazers_count" in body && typeof body.stargazers_count === "number"
|
||||||
|
? compactNumberFormatter.format(body.stargazers_count)
|
||||||
|
: githubLink.fallbackStars,
|
||||||
|
)
|
||||||
|
.catch(() => githubLink.fallbackStars)
|
||||||
|
}, "getGitHubStars")
|
||||||
|
|
||||||
export default function StatsHome() {
|
export default function StatsHome() {
|
||||||
getRequestEvent()?.response.headers.set(
|
getRequestEvent()?.response.headers.set(
|
||||||
"Cache-Control",
|
"Cache-Control",
|
||||||
"public, max-age=60, s-maxage=300, stale-while-revalidate=86400",
|
"public, max-age=60, s-maxage=300, stale-while-revalidate=86400",
|
||||||
)
|
)
|
||||||
const data = createAsync(() => getData())
|
const data = createAsync(() => getData())
|
||||||
|
const githubStars = createAsync(() => getGitHubStars())
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main data-page="stats">
|
<main data-page="stats">
|
||||||
@@ -76,7 +105,7 @@ export default function StatsHome() {
|
|||||||
<Link rel="preload" href={ibmPlexMonoMediumLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
<Link rel="preload" href={ibmPlexMonoMediumLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
||||||
<Link rel="preload" href={ibmPlexMonoSemiBoldLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
<Link rel="preload" href={ibmPlexMonoSemiBoldLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
||||||
<Link rel="preload" href={ibmPlexMonoBoldLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
<Link rel="preload" href={ibmPlexMonoBoldLatin1} as="font" type="font/woff2" crossorigin="anonymous" />
|
||||||
<Header />
|
<Header githubStars={githubStars() ?? githubLink.fallbackStars} />
|
||||||
<div data-component="container">
|
<div data-component="container">
|
||||||
<div data-component="content">
|
<div data-component="content">
|
||||||
<Show when={data()} fallback={<StatsLoading />}>
|
<Show when={data()} fallback={<StatsLoading />}>
|
||||||
@@ -1211,7 +1240,7 @@ function formatSessionCost(value: number) {
|
|||||||
return `$${value.toFixed(4)}`
|
return `$${value.toFixed(4)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function Header() {
|
function Header(props: { githubStars: string }) {
|
||||||
const [menuOpen, setMenuOpen] = createSignal(false)
|
const [menuOpen, setMenuOpen] = createSignal(false)
|
||||||
const [menuViewport, setMenuViewport] = createSignal(false)
|
const [menuViewport, setMenuViewport] = createSignal(false)
|
||||||
|
|
||||||
@@ -1264,12 +1293,13 @@ function Header() {
|
|||||||
<a
|
<a
|
||||||
data-slot="header-button"
|
data-slot="header-button"
|
||||||
data-variant="neutral"
|
data-variant="neutral"
|
||||||
href="https://github.com/sst/opencode"
|
href={githubLink.href}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
aria-label={`${githubLink.ariaLabel} (${props.githubStars} stars)`}
|
||||||
>
|
>
|
||||||
<strong>GitHub</strong>
|
<strong>{githubLink.label}</strong>
|
||||||
<span>[150K]</span>
|
<span>[{props.githubStars}]</span>
|
||||||
</a>
|
</a>
|
||||||
<a data-slot="header-button" data-variant="contrast" href="https://opencode.ai/">
|
<a data-slot="header-button" data-variant="contrast" href="https://opencode.ai/">
|
||||||
<strong>Try OpenCode</strong>
|
<strong>Try OpenCode</strong>
|
||||||
@@ -1294,12 +1324,13 @@ function Header() {
|
|||||||
<a
|
<a
|
||||||
data-slot="mobile-menu-item"
|
data-slot="mobile-menu-item"
|
||||||
data-variant="github"
|
data-variant="github"
|
||||||
href="https://github.com/sst/opencode"
|
href={githubLink.href}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
aria-label={`${githubLink.ariaLabel} (${props.githubStars} stars)`}
|
||||||
>
|
>
|
||||||
<strong>GitHub</strong>
|
<strong>{githubLink.label}</strong>
|
||||||
<span>[150K]</span>
|
<span>[{props.githubStars}]</span>
|
||||||
</a>
|
</a>
|
||||||
<For each={headerLinks}>
|
<For each={headerLinks}>
|
||||||
{(link) => (
|
{(link) => (
|
||||||
@@ -1379,7 +1410,7 @@ function Footer() {
|
|||||||
{ href: "mailto:hello@opencode.ai", label: "Contact us" },
|
{ href: "mailto:hello@opencode.ai", label: "Contact us" },
|
||||||
{ href: "https://opencode.ai/discord", label: "Community" },
|
{ href: "https://opencode.ai/discord", label: "Community" },
|
||||||
{ href: "https://x.com/opencode", label: "X" },
|
{ href: "https://x.com/opencode", label: "X" },
|
||||||
{ href: "https://github.com/anomalyco/opencode", label: "GitHub" },
|
githubLink,
|
||||||
{ href: "https://www.youtube.com/@anomaly-co", label: "YouTube" },
|
{ href: "https://www.youtube.com/@anomaly-co", label: "YouTube" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user