From 67b37924263220ef8193fd8bbfa5f306f0517cb3 Mon Sep 17 00:00:00 2001 From: Rohit Ghumare <48523873+rohitg00@users.noreply.github.com> Date: Sat, 7 Feb 2026 13:42:08 +0000 Subject: [PATCH] feat: show live Product Hunt upvotes, remove Apache license from stats bar --- docs/skillkit/App.tsx | 18 +++++++++--------- docs/skillkit/hooks/useStats.ts | 24 ++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/docs/skillkit/App.tsx b/docs/skillkit/App.tsx index 3da0705f..b003567b 100644 --- a/docs/skillkit/App.tsx +++ b/docs/skillkit/App.tsx @@ -180,15 +180,15 @@ export default function App(): React.ReactElement { Featured - - · - - Apache 2.0 + {stats.phUpvotes > 0 && ( + <> + · + + + + {stats.phUpvotes} + + )} diff --git a/docs/skillkit/hooks/useStats.ts b/docs/skillkit/hooks/useStats.ts index b9d4d61c..9775699e 100644 --- a/docs/skillkit/hooks/useStats.ts +++ b/docs/skillkit/hooks/useStats.ts @@ -4,6 +4,7 @@ interface Stats { version: string; downloads: string; stars: number; + phUpvotes: number; loading: boolean; } @@ -57,6 +58,7 @@ export function useStats(): Stats { version: '1.9.0', downloads: '2.4k', stars: 66, + phUpvotes: 0, loading: true, }); @@ -69,13 +71,19 @@ export function useStats(): Stats { async function fetchStats(): Promise { try { - const [npmResponse, githubResponse] = await Promise.allSettled([ + const [npmResponse, githubResponse, phResponse] = await Promise.allSettled([ fetch('https://api.npmjs.org/downloads/point/last-month/skillkit'), fetch('https://api.github.com/repos/rohitg00/skillkit'), + fetch('https://api.producthunt.com/v2/api/graphql', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: '{ post(slug: "skillkit-2") { votesCount } }' }), + }), ]); let downloads = '2.4k'; let stars = 66; + let phUpvotes = 0; let version = '1.9.0'; if (npmResponse.status === 'fulfilled' && npmResponse.value.ok) { @@ -92,6 +100,18 @@ export function useStats(): Stats { } } + if (phResponse.status === 'fulfilled' && phResponse.value.ok) { + try { + const phData = await phResponse.value.json(); + const votes = phData?.data?.post?.votesCount; + if (typeof votes === 'number' && Number.isFinite(votes)) { + phUpvotes = votes; + } + } catch { + // PH API may require auth, fall back silently + } + } + try { const registryResponse = await fetch('https://registry.npmjs.org/skillkit/latest'); if (registryResponse.ok) { @@ -104,7 +124,7 @@ export function useStats(): Stats { // Use default version } - const newStats = { version, downloads, stars }; + const newStats = { version, downloads, stars, phUpvotes }; setCachedStats(newStats); setStats({ ...newStats, loading: false }); } catch {