From 15ddd8064f0f0a41b9ff242309ae5e7be6f86e6d Mon Sep 17 00:00:00 2001 From: Jaydeep Rusia Date: Tue, 12 May 2026 13:37:54 +0530 Subject: [PATCH] Branch name: `feature/github-stars-banner` Add GitHub stars badge across public pages * Add reusable GitHubStarsLink component * Fetch and cache GitHub star count in localStorage * Format large star counts with compact notation * Add GitHub stars link to landing and auth pages * Add GitHub stars link to app shell and contact page * Improve header and footer layout formatting * Remove unused navigation dependency from app shell * Add abort handling for GitHub API requests --- frontend/src/components/GitHubStarsLink.jsx | 67 +++++++++++++++++++++ frontend/src/pages/AppShell.jsx | 30 ++++++--- frontend/src/pages/AuthCallback.jsx | 7 +++ frontend/src/pages/AuthForm.jsx | 24 +++++--- frontend/src/pages/ContactFeedback.jsx | 4 ++ frontend/src/pages/Landing.jsx | 4 ++ frontend/src/pages/SharedDiagnosis.jsx | 4 ++ 7 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 frontend/src/components/GitHubStarsLink.jsx diff --git a/frontend/src/components/GitHubStarsLink.jsx b/frontend/src/components/GitHubStarsLink.jsx new file mode 100644 index 0000000..7b21592 --- /dev/null +++ b/frontend/src/components/GitHubStarsLink.jsx @@ -0,0 +1,67 @@ +import React from "react"; + +const GITHUB_REPO = "jaydeeprusia/kill-switch"; +const GITHUB_REPO_URL = `https://github.com/${GITHUB_REPO}`; +const GITHUB_STARS_CACHE_KEY = "killswitch_github_stars"; + +function formatStarCount(count) { + if (count >= 1000000) { + return `${(count / 1000000).toFixed(1).replace(/\.0$/, "")}M`; + } + if (count >= 1000) { + return `${(count / 1000).toFixed(1).replace(/\.0$/, "")}K`; + } + return `${count}`; +} + +export default function GitHubStarsLink({ className = "", testId = "github-link" }) { + const [starCount, setStarCount] = React.useState(null); + + React.useEffect(() => { + let ignore = false; + + const cachedStars = window.localStorage.getItem(GITHUB_STARS_CACHE_KEY); + if (cachedStars && !Number.isNaN(Number(cachedStars))) { + setStarCount(Number(cachedStars)); + } + + const controller = new AbortController(); + + fetch(`https://api.github.com/repos/${GITHUB_REPO}`, { + signal: controller.signal, + }) + .then((res) => { + if (!res.ok) throw new Error(`GitHub API error: ${res.status}`); + return res.json(); + }) + .then((data) => { + if (ignore || typeof data?.stargazers_count !== "number") return; + setStarCount(data.stargazers_count); + window.localStorage.setItem(GITHUB_STARS_CACHE_KEY, String(data.stargazers_count)); + }) + .catch(() => { + // Keep cached value if API call fails. + }); + + return () => { + ignore = true; + controller.abort(); + }; + }, []); + + return ( + + + {typeof starCount === "number" ? formatStarCount(starCount) : "-"} + + ); +} diff --git a/frontend/src/pages/AppShell.jsx b/frontend/src/pages/AppShell.jsx index 7b909cc..81a6c78 100644 --- a/frontend/src/pages/AppShell.jsx +++ b/frontend/src/pages/AppShell.jsx @@ -1,14 +1,14 @@ import React from "react"; -import { Link, useLocation, useNavigate } from "react-router-dom"; +import { Link, useLocation } from "react-router-dom"; import { useAuth } from "../lib/auth"; +import GitHubStarsLink from "../components/GitHubStarsLink"; export default function AppShell({ children }) { const { user, logout } = useAuth(); const location = useLocation(); - const navigate = useNavigate(); const nav = [ - {to: "/", label: "Home" }, + { to: "/", label: "Home" }, { to: "/dashboard", label: "Ideas" }, { to: "/new", label: "New idea" }, { to: "/profile", label: "Profile" }, @@ -57,6 +57,9 @@ export default function AppShell({ children }) {
+ {user && (
-
{children}
+
+ {children} +