From 843812ccda69e06028f5e7002a4d175c0597ca47 Mon Sep 17 00:00:00 2001 From: Anvita Prasad Date: Thu, 19 Mar 2026 10:12:46 +0530 Subject: [PATCH 1/4] feat: add GitHub icon to navbar corner Made-with: Cursor --- components/NavBar.vue | 112 +++++++++++++++++++++------------- composables/useGitHubStars.ts | 23 +++++++ pages/index.vue | 15 +++++ 3 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 composables/useGitHubStars.ts diff --git a/components/NavBar.vue b/components/NavBar.vue index 1e557db35..320d9a381 100644 --- a/components/NavBar.vue +++ b/components/NavBar.vue @@ -1,13 +1,13 @@ - -
+ +
Library @@ -103,45 +106,62 @@
- - - -
+ + +
@@ -156,7 +176,7 @@ const isHamburgerShown = ref(false) const isSmallDisplay = useBreakpoints(breakpointsTailwind).smallerOrEqual('md') -defineProps({ +const props = defineProps({ showLogo: { type: Boolean, default: false, @@ -169,8 +189,16 @@ defineProps({ type: Boolean, default: false, }, + showGitHubLink: { + type: Boolean, + default: false, + }, }) +const { stars } = props.showGitHubLink + ? useGitHubStars('JabRef/jabref') + : { stars: ref(null) } + const { resolveClient } = useApolloClient() const { mutate: logout, onDone } = useMutation( diff --git a/composables/useGitHubStars.ts b/composables/useGitHubStars.ts new file mode 100644 index 000000000..8058841fa --- /dev/null +++ b/composables/useGitHubStars.ts @@ -0,0 +1,23 @@ +export function useGitHubStars(repo: string) { + const stars = ref(null) + + if (import.meta.client) { + fetch(`https://api.github.com/repos/${repo}`) + .then((res) => res.json()) + .then((data: { stargazers_count?: number }) => { + if (data.stargazers_count !== undefined) { + stars.value = formatStarCount(data.stargazers_count) + } + }) + .catch(() => {}) + } + + return { stars } +} + +function formatStarCount(count: number): string { + if (count >= 1000) { + return `${(count / 1000).toFixed(1).replace(/\.0$/, '')}K` + } + return count.toString() +} diff --git a/pages/index.vue b/pages/index.vue index 09515b4a2..6e0c2e755 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -5,6 +5,7 @@
{{ link.title }} +
  • + + + GitHub + +
  • From 8056516ba775f2e31ca63a7bab093beb84105752 Mon Sep 17 00:00:00 2001 From: Anvita Prasad Date: Thu, 19 Mar 2026 10:18:18 +0530 Subject: [PATCH 2/4] fix: pin GitHub icon to navbar corner Made-with: Cursor --- components/NavBar.vue | 87 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/components/NavBar.vue b/components/NavBar.vue index 320d9a381..435fea949 100644 --- a/components/NavBar.vue +++ b/components/NavBar.vue @@ -1,6 +1,6 @@ From 30ec6385d05fa7f6e2cf72f2ac3996a1b89bcb4f Mon Sep 17 00:00:00 2001 From: Anvita Prasad Date: Thu, 19 Mar 2026 15:22:05 +0530 Subject: [PATCH 3/4] feat: Add GitHub link with star count to navbar --- components/NavBar.vue | 6 +++--- composables/useGitHubStars.ts | 19 +++++++++++++------ pages/index.vue | 2 +- server/api/githubStars.ts | 31 +++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 server/api/githubStars.ts diff --git a/components/NavBar.vue b/components/NavBar.vue index 435fea949..ebe663cf2 100644 --- a/components/NavBar.vue +++ b/components/NavBar.vue @@ -143,7 +143,7 @@ class="flex-1 flex items-center justify-end mx-3 md:mx-6" > (null) } diff --git a/composables/useGitHubStars.ts b/composables/useGitHubStars.ts index 8058841fa..13e008cc8 100644 --- a/composables/useGitHubStars.ts +++ b/composables/useGitHubStars.ts @@ -2,14 +2,21 @@ export function useGitHubStars(repo: string) { const stars = ref(null) if (import.meta.client) { - fetch(`https://api.github.com/repos/${repo}`) - .then((res) => res.json()) - .then((data: { stargazers_count?: number }) => { - if (data.stargazers_count !== undefined) { - stars.value = formatStarCount(data.stargazers_count) + fetch(`/api/githubStars?repo=${encodeURIComponent(repo)}`) + .then((res) => { + if (!res.ok) { + throw new Error(`Failed to fetch GitHub stars: ${res.statusText}`) } + return res.json() + }) + .then((data: { stars?: number }) => { + if (data.stars !== undefined) { + stars.value = formatStarCount(data.stars) + } + }) + .catch((error) => { + console.debug('Failed to fetch GitHub stars:', error) }) - .catch(() => {}) } return { stars } diff --git a/pages/index.vue b/pages/index.vue index 6e0c2e755..b96a1f6c0 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -5,7 +5,7 @@
    { + const query = getQuery(event) + const repo = query.repo as string + + if (!repo) { + throw createError({ + statusCode: 400, + message: 'Missing repo parameter', + }) + } + + try { + const response = await fetch(`https://api.github.com/repos/${repo}`) + + if (!response.ok) { + throw new Error(`GitHub API responded with ${response.status}`) + } + + const data = (await response.json()) as { stargazers_count?: number } + + return { + stars: data.stargazers_count ?? 0, + } + } catch (error) { + console.debug('Failed to fetch GitHub stars for repo', repo, error) + throw createError({ + statusCode: 500, + message: 'Failed to fetch GitHub stars', + }) + } +}) From d3de0020d0fe8c449cf68fb67036ed343f0d0127 Mon Sep 17 00:00:00 2001 From: Anvita Prasad Date: Mon, 23 Mar 2026 12:20:25 +0530 Subject: [PATCH 4/4] fix: cache GitHub stars and hardcode repo --- components/NavBar.vue | 2 +- composables/useGitHubStars.ts | 4 +-- server/api/githubStars.ts | 66 ++++++++++++++++++++++------------- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/components/NavBar.vue b/components/NavBar.vue index ebe663cf2..f2762ef22 100644 --- a/components/NavBar.vue +++ b/components/NavBar.vue @@ -195,7 +195,7 @@ const props = defineProps({ }) const { stars } = props.showGithubLink - ? useGitHubStars('JabRef/jabref') + ? useGitHubStars() : { stars: ref(null) } const { resolveClient } = useApolloClient() diff --git a/composables/useGitHubStars.ts b/composables/useGitHubStars.ts index 13e008cc8..80089bade 100644 --- a/composables/useGitHubStars.ts +++ b/composables/useGitHubStars.ts @@ -1,8 +1,8 @@ -export function useGitHubStars(repo: string) { +export function useGitHubStars() { const stars = ref(null) if (import.meta.client) { - fetch(`/api/githubStars?repo=${encodeURIComponent(repo)}`) + fetch('/api/githubStars') .then((res) => { if (!res.ok) { throw new Error(`Failed to fetch GitHub stars: ${res.statusText}`) diff --git a/server/api/githubStars.ts b/server/api/githubStars.ts index 543e6f309..fece7d443 100644 --- a/server/api/githubStars.ts +++ b/server/api/githubStars.ts @@ -1,31 +1,49 @@ -export default defineEventHandler(async (event) => { - const query = getQuery(event) - const repo = query.repo as string +/** JabRef desktop app repo — fixed to avoid open proxy / rate-limit abuse */ +const JABREF_REPO = 'JabRef/jabref' - if (!repo) { - throw createError({ - statusCode: 400, - message: 'Missing repo parameter', - }) - } +export default defineCachedEventHandler( + async (event) => { + event.node.res.setHeader( + 'Cache-Control', + 'public, s-maxage=300, stale-while-revalidate=600', + ) - try { - const response = await fetch(`https://api.github.com/repos/${repo}`) + const config = useRuntimeConfig() + const githubToken = config.githubRepoToken as string | undefined - if (!response.ok) { - throw new Error(`GitHub API responded with ${response.status}`) + const headers: Record = { + Accept: 'application/vnd.github.v3+json', + 'User-Agent': 'jabref-online', } + if (githubToken) { + headers.Authorization = `Bearer ${githubToken}` + } + + try { + const response = await fetch( + `https://api.github.com/repos/${JABREF_REPO}`, + { headers }, + ) + + if (!response.ok) { + throw new Error(`GitHub API responded with ${response.status}`) + } - const data = (await response.json()) as { stargazers_count?: number } + const data = (await response.json()) as { stargazers_count?: number } - return { - stars: data.stargazers_count ?? 0, + return { + stars: data.stargazers_count ?? 0, + } + } catch (error) { + console.debug('Failed to fetch GitHub stars for repo', JABREF_REPO, error) + throw createError({ + statusCode: 500, + message: 'Failed to fetch GitHub stars', + }) } - } catch (error) { - console.debug('Failed to fetch GitHub stars for repo', repo, error) - throw createError({ - statusCode: 500, - message: 'Failed to fetch GitHub stars', - }) - } -}) + }, + { + name: 'github-stars-jabref', + maxAge: 300, + }, +)