a54d1cfeaffd0b568487aa1fbdc4473f363c2fe2
git-activity-merge
Small self-hosted FastAPI service that merges GitHub + Gitea contribution data and returns embeddable contribution heatmap images.
Example for GitHub profile README:

What It Does
- Fetches contribution data from:
- GitHub GraphQL API (
GITHUB_USERNAME, optionalGITHUB_TOKEN) - Gitea heatmap API (
{GITEA_BASE_URL}/api/v1/users/{GITEA_USERNAME}/heatmap)
- GitHub GraphQL API (
- Normalizes into date-based counts:
githubgiteatotal
- Caches source responses and rendered images on disk.
- Returns:
- merged JSON
- GitHub-style SVG heatmap
- PNG heatmap
API Routes
GET /healthGET /activity.jsonGET /activity.svgGET /activity.png
Supported query params:
year=YYYYordays=365(mutually exclusive)theme=dark|lightsource=all|github|gitea
Examples:
curl "http://localhost:8000/activity.json?days=365&source=all"
curl "http://localhost:8000/activity.svg?year=2026&theme=dark"
curl "http://localhost:8000/activity.png?days=180&source=gitea"
Setup
1. Install
python -m venv .venv
. .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
2. Configure
Copy .env.example to .env and edit values.
Required:
GITHUB_USERNAMEGITEA_BASE_URLGITEA_USERNAME
Optional:
GITHUB_TOKENGITEA_TOKENCACHE_TTL_SECONDS(default:3600)CACHE_DIR(default:./cachelocally,/app/cachein container)DEFAULT_THEME(lightordark, default:light)SERVICE_TITLE(default:git-activity-merge)
3. Run
uvicorn app.main:app --reload --port 8000
Docker
docker compose up --build
Container serves on port 8000 and mounts a named cache volume at /app/cache.
Reverse Proxy Example (Nginx)
server {
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Then embed directly:

Notes
- GitHub GraphQL without token is possible but lower-rate/less reliable. Set
GITHUB_TOKENfor stability. - Gitea instances may require
GITEA_TOKENfor private activity or stricter rate limits. - If upstream APIs fail and stale cache exists,
/activity.jsonincludes"stale": trueand stale data is served.
Description
Languages
Python
98.6%
Dockerfile
1.4%