Skip to content

Nannoy/git-folio

Repository files navigation

@nannoy/git-folio

Embeddable GitHub stats card for developer portfolios. No API token required — works entirely with public GitHub data.

Install

npm install @nannoy/git-folio

Quick Start — Vanilla JS

import { fetchGitHubStats } from "@nannoy/git-folio";

const stats = await fetchGitHubStats({ username: "torvalds" });

console.log(stats.totalStars);            // number
console.log(stats.totalCommits);          // number (from GitHub Search API)
console.log(stats.topLanguages);          // LanguageStat[]
console.log(stats.contributionStreak);    // number — consecutive days
console.log(stats.contributionCalendar);  // ContributionWeek[]

React Component

import { GitFolioCard } from "@nannoy/git-folio/react";

export default function Portfolio() {
  return (
    <GitFolioCard
      username="torvalds"
      theme="auto"
      variant="full"
      accentColor="#2dd4bf"
    />
  );
}

How it works (no token)

All data is fetched from public GitHub endpoints in parallel:

Data Source
Profile, repos, stars, forks, followers GitHub REST API (/users/{u}, /users/{u}/repos)
Top languages + colors REST repos list + bundled color map
Commit count GitHub Search API (/search/commits?q=author:{u})
PR count GitHub Search API (/search/issues?q=author:{u}+type:pr)
Issue count GitHub Search API (/search/issues?q=author:{u}+type:issue)
Contribution heatmap, streak github-contributions-api.jogruber.de

Rate limits (unauthenticated):

  • REST API: 60 requests/hour per IP
  • Search API: 10 requests/minute per IP (separate bucket)
  • Contributions proxy: cached 1 hour

For server-side rendering, cache the result and revalidate on a schedule — the built-in cache option handles this: fetchGitHubStats({ username, cache: 3600 }).

React Props

Prop Type Default Description
username string required GitHub username
theme 'light' | 'dark' | 'auto' 'auto' Color theme — auto follows system preference
variant 'compact' | 'full' 'full' compact shows avatar, name, and 4 key stats only
accentColor string #2dd4bf Hex color for accents and heatmap tint
showContributions boolean true Show contribution heatmap
showLanguages boolean true Show top languages bar
className string Extra CSS class on the card element

GitFolioStats type

interface GitFolioStats {
  name: string;
  login: string;
  avatarUrl: string;
  bio: string | null;
  location: string | null;
  websiteUrl: string | null;
  followers: number;
  following: number;
  totalRepositories: number;
  totalStars: number;
  totalForks: number;
  totalCommits: number | null;      // null only if Search API rate-limited
  totalPullRequests: number | null; // null only if Search API rate-limited
  totalIssues: number | null;       // null only if Search API rate-limited
  totalContributions: number;
  topLanguages: LanguageStat[];
  contributionStreak: number;
  contributionCalendar: ContributionWeek[];
}

Error Handling

import { fetchGitHubStats, GitFolioError } from "@nannoy/git-folio";

try {
  const stats = await fetchGitHubStats({ username });
} catch (err) {
  if (err instanceof GitFolioError) {
    console.error(err.code);        // 'RATE_LIMITED' | 'USER_NOT_FOUND' | 'NETWORK_ERROR' | ...
    console.error(err.retryAfter);  // Date | undefined
  }
}
Error code Cause
RATE_LIMITED GitHub REST API rate limit hit
USER_NOT_FOUND Username doesn't exist on GitHub
NETWORK_ERROR DNS / fetch failure
HTTP_ERROR Non-200 GitHub API response
PARSE_ERROR Unexpected response body

Theming

CSS custom properties can be overridden on any ancestor:

.my-portfolio {
  --gf-accent: #a78bfa;
  --gf-accent-rgb: 167, 139, 250;
  --gf-radius: 12px;
  --gf-font: "Inter", sans-serif;
}

License

MIT — github.com/Nannoy/git-folio

About

Embeddable GitHub stats card for developer portfolios

Resources

License

Stars

7 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors