One compact, animated, fully-customizable GitHub stats card. Self-hostable · one image · any username · exact colors.
Public stat-card services (github-readme-stats, github-profile-trophy) frequently go down (rate limits) and can't honor exact custom colors. gitfolio is a single, self-hosted endpoint that renders everything you need in one compact SVG — avatar, key stats, top languages, streak, contribution activity, and your tech stack — with full control over colors and which sections appear.
Add one image to your profile README.md (swap INSTANCE for your deployed domain and set your username):
Or build it visually with the interactive builder — pick colors, toggle sections, choose your stack, copy the snippet.
GET /api/card
| Param | Description | Default |
|---|---|---|
username |
GitHub username (required) | — |
theme |
Preset: dark, gold, light, radical, dracula, ocean, sunset, forest |
dark |
primary |
Accent/title color (hex, no #) |
theme |
secondary |
Icons/streak-ring color | theme |
bg |
Background color, or gradient deg,c1,c2 |
theme |
bg2 |
Second gradient stop | — |
sections |
Comma list of header,stats,langs,streak,activity,stack,social |
all |
stack |
Comma list of tech slugs, e.g. dotnet,react,docker |
— |
stack_mono |
Tint stack icons with the secondary color instead of brand colors |
false |
social |
Comma list of platform:handle, e.g. github:you,linkedin:you |
— |
social_show |
How each social renders: handle, name, or icon |
handle |
social_mono |
Tint social icons with the secondary color |
false |
all_commits |
Count all-time commits (slower) instead of last year | false |
animation |
Set false to disable animations |
true |
hide_border |
Hide the card border | false |
brand |
Show a faint watermark link in the bottom-right corner; set false to hide |
true |
cache_seconds |
Cache TTL (clamped 43200–172800) | 86400 |
Any Simple Icons slug works (e.g. docker, redis, angular, typescript). Friendly aliases: node, vue, next, postgres, k8s, cs, dotnet, tailwind, html, css, gcp, kafka, mssql. Brands dropped from Simple Icons for trademark reasons (csharp, aws, azure, visualstudio, …) ship as bundled logos. The few with no logo anywhere (wpf, maui, winforms, blazor, …) render as neat text badges. Near-black logos are auto-lightened for dark backgrounds.
social=github:muqimjon,linkedin:muqimjon,telegram:you adds a CONNECT row. Each entry is platform:handle — platform is a Simple Icons slug (github, linkedin, telegram, x, gmail, instagram, youtube, discord, …) drawn as an icon, handle is your username on it. Pick the layout with social_show:
handle(default) →[logo] muqimjonname→[logo] Telegramicon→[logo]only
Handles resolve to real links (github:muqimjon → https://github.com/muqimjon, gmail:you@x.com → mailto:…); pass a full https://… as the handle to override. The links are real <a> elements, so they're clickable when the card is opened as an SVG or embedded with <object>. On a GitHub README the card is served through an <img> proxy, which renders it as a static image — per-icon links won't be clickable there. To make the whole card a link, wrap it: [](https://github.com/you).
When animation is on (default), sections fade in on load, the activity line draws left→right, the current-streak ring sweeps like a clock, and every number counts up from zero. Everything honors prefers-reduced-motion and falls back to a correct static card, so it stays readable even where GitHub's image proxy renders only the first frame.
gitfolio is written in TypeScript: a static folder (public/) plus one Function that shares a single platform‑neutral core (src/handler.ts). It runs on Cloudflare Pages (via functions/api/card.ts) or Vercel (via api/card.ts). A tiny build step bundles the browser builder (src/client/builder.ts → public/builder.js); the Function is bundled by the platform. One env var.
The static builder is served from public/; the /api/card endpoint is a Pages Function in functions/.
- Fork this repo. In the Cloudflare dashboard: Workers & Pages → Create → Pages → Connect to Git, pick your fork.
- Build settings:
- Framework preset: None
- Build command:
npm install && npm run build - Build output directory:
public - Functions in
/functionsare detected automatically. Nonodejs_compatflag needed — the code uses only Web APIs.
- Create a classic Personal Access Token with no scopes checked (public data only).
- Settings → Environment variables → Production → add
GH_TOKEN= your token → redeploy. - Builder:
https://YOUR-PROJECT.pages.dev· Card:…/api/card?username=ANYONE.
Import the repo, set GH_TOKEN, deploy. Vercel runs npm run build, serves public/ at the root, and turns api/card.ts into the function automatically.
| Var | Purpose |
|---|---|
GH_TOKEN |
GitHub token (required). |
PAT_1, PAT_2, … |
Optional extra tokens; gitfolio rotates through them to multiply the rate limit. |
WHITELIST |
Optional comma-separated usernames this instance will serve. Empty = anyone. |
CACHE_SECONDS |
Optional fixed cache TTL (overrides the per-request clamp). |
npm install
echo "GH_TOKEN=your_token" > .env
npm run dev # builds the bundle, serves http://localhost:8787
npm run preview -- muqimjon --theme=gold --out=out.svg # render to a file
npm run typecheck # tsc --noEmit- Tech icons from Simple Icons (CC0). UI glyphs from Octicons (MIT).
- Contribution/stat concepts inspired by github-readme-stats (MIT).
MIT © Muqimjon Mamadaliyev