From 75c0f70502ea50bc7a542711f4b8a20f42e92c01 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 19 Dec 2025 20:18:19 +0000 Subject: [PATCH] Implement localStorage caching for GitHub stars count Add 1-hour cache to prevent excessive API calls and rate limiting. The cache stores star count with timestamp and automatically expires after 1 hour. Falls back to API call when cache is missing or expired. --- apps/landing/src/app/StarButton.tsx | 55 ++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/apps/landing/src/app/StarButton.tsx b/apps/landing/src/app/StarButton.tsx index 9a6b9bee..e328214f 100644 --- a/apps/landing/src/app/StarButton.tsx +++ b/apps/landing/src/app/StarButton.tsx @@ -13,12 +13,62 @@ const spin = keyframes({ }, }) +const CACHE_KEY = 'github_star_count' +const CACHE_DURATION = 60 * 60 * 1000 // 1 hour in milliseconds + +interface CachedData { + count: number + timestamp: number +} + export default function StarButton() { const [starCount, setStarCount] = useState(null) useEffect(() => { const abortController = new AbortController() + + const getCachedData = (): CachedData | null => { + try { + const cached = localStorage.getItem(CACHE_KEY) + if (!cached) return null + + const data: CachedData = JSON.parse(cached) + const now = Date.now() + + // Check if cache is still valid + if (now - data.timestamp < CACHE_DURATION) { + return data + } + + // Cache expired, remove it + localStorage.removeItem(CACHE_KEY) + return null + } catch { + return null + } + } + + const setCachedData = (count: number) => { + try { + const data: CachedData = { + count, + timestamp: Date.now(), + } + localStorage.setItem(CACHE_KEY, JSON.stringify(data)) + } catch { + // Ignore localStorage errors + } + } + const fetchStarCount = async () => { + // Try to get from cache first + const cached = getCachedData() + if (cached) { + setStarCount(cached.count) + return + } + + // If no cache, fetch from API try { const data = await fetch( 'https://api.github.com/repos/dev-five-git/devup-ui', @@ -26,7 +76,10 @@ export default function StarButton() { signal: abortController.signal, }, ).then((res) => res.json()) - setStarCount(data.stargazers_count) + + const count = data.stargazers_count + setStarCount(count) + setCachedData(count) } catch (error) { if (error !== 'unmounted') console.error(error) } finally {