Skip to content

feat: Add GitHub link with star count to navbar#2926

Open
AnvitaPrasad wants to merge 4 commits intoJabRef:mainfrom
AnvitaPrasad:feat/2518-github-link-title-bar
Open

feat: Add GitHub link with star count to navbar#2926
AnvitaPrasad wants to merge 4 commits intoJabRef:mainfrom
AnvitaPrasad:feat/2518-github-link-title-bar

Conversation

@AnvitaPrasad
Copy link

@AnvitaPrasad AnvitaPrasad commented Mar 20, 2026

🔗 Linked issue

Resolves #2518

📚 Description

Added a GitHub icon with star count to the top-right corner of the landing page navbar, similar to other open-source projects like Nuxt.com. This makes it easier for users to navigate to the JabRef GitHub repository directly from the website.

Screenshot 2026-03-21 at 12 41 39 AM

Changes:

  • Added showGithubLink prop to NavBar component
  • Created server endpoint /api/githubStars to fetch GitHub star count with caching
  • Created useGitHubStars composable to fetch and format star count
  • Positioned GitHub icon in navbar's right corner

Copilot AI review requested due to automatic review settings March 20, 2026 19:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a GitHub repository link with a live star count to the landing page navigation bar, supporting issue #2518 by making the repo easier to reach from the site header.

Changes:

  • Adds a showGithubLink prop to NavBar and renders a GitHub icon + star count on the right side (desktop).
  • Introduces /api/githubStars to fetch star counts from the GitHub REST API.
  • Adds useGitHubStars composable and wires it into NavBar; adds a GitHub link entry to the collapsed (mobile) menu on the homepage.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
server/api/githubStars.ts New API endpoint to fetch stargazer count from GitHub
composables/useGitHubStars.ts New composable to fetch/format star count from the new API
components/NavBar.vue Adds showGithubLink prop and renders the GitHub icon + star count on desktop
pages/index.vue Enables the GitHub link on the landing page navbar and adds a mobile-menu GitHub link

Comment on lines +1 to +31
export default defineEventHandler(async (event) => {
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',
})
}
})
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions caching, but this endpoint currently fetches GitHub on every request. In production this is likely to hit GitHub’s unauthenticated rate limits and adds latency to every page view. Consider adding server-side caching (e.g., Nitro storage-based TTL cache / cached event handler) and/or setting appropriate cache headers so repeated requests reuse the cached star count for a period (e.g., 5–30 minutes).

Suggested change
export default defineEventHandler(async (event) => {
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',
})
}
})
export default defineCachedEventHandler(
async (event) => {
const query = getQuery(event)
const repo = query.repo as string
if (!repo) {
throw createError({
statusCode: 400,
message: 'Missing repo parameter',
})
}
// Allow shared caches (CDN/reverse proxy) to reuse this response.
// This is aligned with the server-side TTL below.
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}`)
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',
})
}
},
{
// Cache the computed star count on the server for 5 minutes
maxAge: 300,
},
)

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +11
const query = getQuery(event)
const repo = query.repo as string

if (!repo) {
throw createError({
statusCode: 400,
message: 'Missing repo parameter',
})
}

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repo is taken directly from the query string and interpolated into the GitHub API path without validation/normalization. Since the UI always queries a single repo, this effectively exposes a public proxy that can be abused to trigger arbitrary GitHub API calls (and burn rate limit). Prefer hardcoding the JabRef repo in the handler (no repo param), or strictly validate the parameter (e.g., owner/name with a tight regex) and reject anything else.

Suggested change
const query = getQuery(event)
const repo = query.repo as string
if (!repo) {
throw createError({
statusCode: 400,
message: 'Missing repo parameter',
})
}
const repo = 'JabRef/jabref'

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +14
try {
const response = await fetch(`https://api.github.com/repos/${repo}`)

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint uses unauthenticated GitHub REST API requests, which are heavily rate-limited (and may fail intermittently under load). The codebase already has runtimeConfig.githubRepoToken used for GitHub API calls (see server/api/getLatestRelease.ts); consider reusing that token here (when set) to raise rate limits and improve reliability, while still keeping caching in place.

Suggested change
try {
const response = await fetch(`https://api.github.com/repos/${repo}`)
const config = useRuntimeConfig()
const githubToken = (config as { githubRepoToken?: string }).githubRepoToken
try {
const headers: Record<string, string> = {
'User-Agent': 'jabref-online',
Accept: 'application/vnd.github.v3+json',
}
if (githubToken) {
headers.Authorization = `token ${githubToken}`
}
const response = await fetch(`https://api.github.com/repos/${repo}`, {
headers,
})

Copilot uses AI. Check for mistakes.
@AnvitaPrasad AnvitaPrasad changed the title Feat/2518 GitHub link title bar Feat: GitHub link in title bar Mar 23, 2026
@AnvitaPrasad AnvitaPrasad changed the title Feat: GitHub link in title bar feat: Add GitHub link with star count to navbar Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve the title bar of main JabRef website

2 participants