# git-contribution-graph A self-hosted Symfony service that merges contribution data from **GitHub**, **GitLab** and **Gitea** into a single GitHub-style heatmap SVG you can embed anywhere. ``` https://your-host/graph.svg?github_user=you&github_token=ghp_…&gitea_user=you&gitea_token=…&gitea_url=https://git.example.com ``` ![Example graph](https://img.shields.io/badge/output-SVG%20heatmap-39d353?style=flat-square) --- ## Features - **Three platforms** — GitHub, GitLab (cloud or self-hosted), Gitea (self-hosted) - **Merged heatmap** — contributions from all sources are summed per day - **GitHub colour palette** — exact dark/light theme tokens - **Embeddable** — returns `image/svg+xml`, works in any `` tag or Markdown - **Cached** — responses cached for 1 hour, safe to embed in public READMEs - **Graceful degradation** — if one platform fails, the others still render --- ## Deploy ### Requirements - Docker + Docker Compose ### 1. Clone and configure ```bash git clone https://git.arthurerlich.de/haylan/git-contribution-graph.git cd git-contribution-graph cp .env .env.local ``` Edit `.env.local`: ```dotenv APP_ENV=prod APP_DEBUG=0 APP_SECRET= ``` ### 2. Start ```bash docker compose up -d ``` The service listens on **port 8080** by default. Put Traefik or nginx in front of it for HTTPS. ### 3. Health check ``` GET /health → {"status":"ok"} ``` --- ## API ### `GET /graph.svg` | Parameter | Required | Description | |---|---|---| | `github_user` | ✗ | GitHub username | | `github_token` | ✗ | GitHub PAT — scope: `read:user` | | `gitlab_user` | ✗ | GitLab username | | `gitlab_token` | ✗ | GitLab PAT — scope: `read_user`, `read_api` | | `gitlab_url` | ✗ | GitLab base URL (default: `https://gitlab.com`) | | `gitea_user` | ✗ | Gitea username | | `gitea_token` | ✗ | Gitea PAT — scope: `read:user` | | `gitea_url` | ✗ | Gitea instance URL, e.g. `https://git.example.com` | | `theme` | ✗ | `dark` (default) or `light` | All platform parameters are optional — include only the ones you use. At least one platform must be configured for a non-empty graph. --- ## Embedding in a README ### GitHub-only ```markdown ![Contribution Graph](https://your-host/graph.svg?github_user=YOUR_USER&github_token=YOUR_TOKEN) ``` ### GitHub + Gitea ```markdown ![Contribution Graph](https://your-host/graph.svg?github_user=YOUR_GH_USER&github_token=GH_TOKEN&gitea_user=YOUR_GITEA_USER&gitea_token=GITEA_TOKEN&gitea_url=https://git.arthurerlich.de) ``` ### All three platforms ```markdown ![Contribution Graph](https://your-host/graph.svg?github_user=GH_USER&github_token=GH_TOKEN&gitlab_user=GL_USER&gitlab_token=GL_TOKEN&gitlab_url=https://gitlab.com&gitea_user=GITEA_USER&gitea_token=GITEA_TOKEN&gitea_url=https://git.arthurerlich.de) ``` ### Dark vs Light theme ```markdown ![Contribution Graph](https://your-host/graph.svg?github_user=USER&github_token=TOKEN&theme=dark) ![Contribution Graph](https://your-host/graph.svg?github_user=USER&github_token=TOKEN&theme=light) ``` > **Security note:** API tokens embedded in public Markdown URLs are visible to anyone. Use read-only fine-grained tokens with minimal scopes. For private repos or sensitive setups, proxy the request server-side and keep tokens in environment variables. --- ## Token setup ### GitHub 1. Go to **Settings → Developer settings → Personal access tokens → Fine-grained tokens** 2. Set **Resource owner** to your account 3. Under **Permissions → Account permissions**, set **Contribution activity** → Read-only 4. Generate and copy the token ### GitLab 1. Go to **User Settings → Access Tokens** 2. Add a token with scopes: `read_user`, `read_api` 3. Generate and copy the token ### Gitea 1. Go to **Settings → Applications → Manage Access Tokens** 2. Add a token with permission: **user** → Read 3. Generate and copy the token --- ## Development ```bash # Install deps composer install # Run dev server APP_ENV=dev php -S localhost:8080 -t public # Test endpoint curl "http://localhost:8080/graph.svg?gitea_user=haylan&gitea_token=YOUR_TOKEN&gitea_url=https://git.arthurerlich.de" -o graph.svg ``` --- ## Architecture ``` GET /graph.svg │ ├─ GitHubProvider → GitHub GraphQL API (contributionCalendar) ├─ GitLabProvider → GitLab REST API (/users/:id/events) └─ GiteaProvider → Gitea REST API (/users/:user/heatmap) │ merge by date (sum counts) │ SvgRenderer │ image/svg+xml (cached 1h) ``` --- ## License MIT