A free, public SVG card service for GitHub profiles. Embed dynamic stats, language breakdowns, contribution streaks, activity heatmaps, pinned repositories, DevOps signals, and coding activity directly in your README — no sign-up, no install, just a URL.
Built with Node.js, Fastify, and TypeScript. MIT-licensed and ready to self-host.
Maintainer: Enoque Sousa
Drop this into your README.md, replacing YOUR_LOGIN with your GitHub username:
That's it. The service fetches your public GitHub data and returns an SVG, which any markdown-aware renderer (GitHub, GitLab, dashboards, blog posts) embeds inline.



All card endpoints require ?username=<github-login> and return image/svg+xml.
| Endpoint | What it shows |
|---|---|
/api/stats |
Profile statistics — commits, PRs, issues, stars, contributions, rank |
/api/top-langs |
Most-used languages — layouts: normal, compact, donut, donut-vertical, pie |
/api/streak |
Contribution streak — mode=daily | weekly |
/api/activity |
Activity heatmap + radar chart |
/api/pin?repo=<name> |
Single pinned repository card |
/api/pin |
Pinned repositories grid |
/api/devops |
CI/CD, CodeFactor, and security-related signals |
/api/coding-stats |
Coding activity derived from public GitHub events (no external service) |
Utility endpoints
| Endpoint | Returns |
|---|---|
GET / |
Machine-readable JSON catalog of all endpoints with every supported parameter, type, default, and example URL |
GET /health |
JSON snapshot — uptime, memory, cache size, GitHub rate-limit headroom per token |
Every card supports the parameters below. Hex colors are passed without the leading #.
| Parameter | Type | Default | Notes |
|---|---|---|---|
theme |
dracula-black | pro-dark |
dracula-black |
Theme id |
locale |
en | pt-br | es |
en |
Card copy language |
hide_title |
bool | false |
|
hide_border |
bool | false |
|
custom_title |
string ≤100 | — | Override default title |
border_radius |
0–50 | 12 |
Card corner radius |
bg_color |
hex | — | Background |
text_color |
hex | — | Body text |
title_color |
hex | — | Title |
icon_color |
hex | — | Icons |
border_color |
hex | — | Border |
disable_animations |
bool | false |
|
cache_seconds |
300–86400 | 14400 |
CDN/client cache hint (4h default) |
| Parameter | Type | Default | Notes |
|---|---|---|---|
include_private |
bool | false |
Count private contributions (requires expanded PAT scope) |
include_archived |
bool | true |
Include archived repos in star count |
include_forks |
bool | false |
Include forked repos in star count |
hide_rank |
bool | false |
Hide the rank badge |
hide |
comma list | — | Hide stat rows: stars, commits, prs, issues, contribs |
show |
comma list | — | Add extra rows: reviews, discussions_started, discussions_answered, prs_merged |
line_height |
20–40 | 25 |
Vertical spacing between rows |
| Parameter | Type | Default | Notes |
|---|---|---|---|
langs_count |
1–100 | 20 |
Max languages to display |
layout |
enum | normal |
normal | compact | donut | donut-vertical | pie |
hide |
comma list | — | Language names to exclude (e.g. HTML,CSS) |
exclude_repo |
comma list | — | Repositories to exclude from aggregation |
include_archived |
bool | true |
Include archived repos |
size_weight |
0–1 | 1 |
Weight given to byte size |
count_weight |
0–1 | 0 |
Weight given to repo count |
| Parameter | Type | Default | Notes |
|---|---|---|---|
mode |
daily | weekly |
daily |
Streak counting granularity |
hide_current_streak |
bool | false |
Hide the current streak section |
hide_longest_streak |
bool | false |
Hide the longest streak section |
Uses only the shared parameters above.
| Parameter | Type | Default | Notes |
|---|---|---|---|
repo |
string | — | Repository name (without owner). Omit for the pinned-repos grid; include for a single-repo card. |
show_owner |
bool | false |
Prefix the repo name with owner/ |
description_lines_count |
1–3 | 1 |
Lines of description to display |
Uses only the shared parameters above.
| Parameter | Type | Default | Notes |
|---|---|---|---|
langs_count |
1–100 | 5 |
Number of top languages to display |
layout |
normal | compact |
normal |
Card layout style |
The machine-readable version of this reference (with exact types, ranges, and per-field descriptions) is always available at
GET /on any running instance.
<!-- Pro Dark with custom title -->

<!-- Donut top-langs in pt-br -->

<!-- Single pinned repo -->

<!-- GitHub-dark color override -->
- The public instance is rate-limited to 60 requests per minute per client IP.
- Responses use long cache hints (
cache_seconds=14400by default), so README embeds rarely hit the limit. - The service is best-effort and free. For high-traffic dashboards or guaranteed availability, please self-host (next section).
The application is a standard Node.js service — no Docker required, though you may containerize it if you prefer.
- Node.js 22 or newer
- One GitHub Personal Access Token (PAT) — fine-scoped, public read is enough; private fields require additional scopes
git clone https://github.com/enoque-studio/engineering-overview-pro.git
cd engineering-overview-pro
npm install
cp .env.example .env
# Edit .env and set PAT_1
npm run devServer listens on http://localhost:3000.
npm ci
npm run build
node dist/server.jsUse systemd, pm2, or any process supervisor for restarts and logs. Put a reverse proxy (Nginx, Traefik, Caddy) in front for TLS and set TRUST_PROXY=true so rate limiting sees the real client IP.
| Variable | Required | Description |
|---|---|---|
PAT_1 |
Yes | GitHub PAT. Add PAT_2, PAT_3, … for round-robin rotation — each token shares the 5 000 req/h quota, so more tokens means more headroom. |
PORT |
No | HTTP port (default 3000) |
HOST |
No | Bind address (default 0.0.0.0) |
LOG_LEVEL |
No | Fastify logger level: info, warn, error, debug (default info) |
TRUST_PROXY |
No | true, false, or comma-separated allow-list. Only enable behind a trusted proxy — otherwise clients can spoof X-Forwarded-For and bypass rate limiting. Default false. |
WARM_USERNAMES |
No | Comma-separated GitHub usernames to pre-warm in the background. The service silently refreshes their data before the cache expires, eliminating cold-start latency for every card embed. |
WARM_INTERVAL_MS |
No | How often the background warmer runs in milliseconds. Default 60000 (1 minute). Floor is 30000 (30 s). Warming only fires when the cache has actually expired, so at normal TTLs the warmer makes ≈ 6 GitHub calls per endpoint per day. |
There is no default username; every card URL must include ?username=.
git pull
npm ci
npm run build
# Restart the process- Keep PATs scoped to the minimum GitHub permissions you need.
- Monitor
/healthfor rate-limit headroom when traffic grows. - Enable
TRUST_PROXYonly when a trusted reverse proxy terminates TLS and setsX-Forwarded-Forcorrectly.
| Script | Description |
|---|---|
npm run dev |
Watch-mode dev server (tsx) |
npm run build |
Compile to dist/ |
npm start |
Run dist/server.js (loads .env when present) |
npm test |
Unit tests (Vitest, includes GraphQL syntax validation) |
npm run test:coverage |
Vitest with V8 coverage report |
npm run lint |
ESLint on src/ |
npm run typecheck |
TypeScript check without emit |
npm run format |
Prettier write |
npm run format:check |
Prettier check (CI) |
npm run spell |
cspell on the full tree |
npm run spell:ci |
cspell on docs + GraphQL queries (CI subset) |
npm run verify |
CI parity: format, lint, typecheck, spell, tests, build, npm audit |
- CI (
.github/workflows/ci.yml) — on every push and PR tomain/dev, runs Prettier, ESLint, TypeScript, spell check, Vitest (including GraphQL syntax validation), production build, andnpm audit --audit-level=high. - Dependabot (
.github/dependabot.yml) — weekly grouped npm updates (Octokit, Fastify, TypeScript/Vitest clusters) and monthly GitHub Actions updates. - Releases (
.github/workflows/release.yml) — pushing av*tag (e.g.v1.0.1) creates a GitHub Release with auto-generated notes; npm publish is opt-in via theNPM_PUBLISHrepo variable +NPM_TOKENsecret.
PRs welcome. See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
See SECURITY.md for reporting vulnerabilities. Please do not include real PATs or secrets in issues — use the disclosure channel listed there.
MIT — see LICENSE.
