{"id":44496956,"url":"https://github.com/leonardokr/leo-git-statistics","last_synced_at":"2026-02-20T04:00:58.511Z","repository":{"id":338099148,"uuid":"1156268676","full_name":"leonardokr/leo-git-statistics","owner":"leonardokr","description":"Generate beautiful, customizable SVG statistics cards for your GitHub profile","archived":false,"fork":false,"pushed_at":"2026-02-13T12:01:44.000Z","size":381,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-13T12:05:43.313Z","etag":null,"topics":["github","github-actions","github-api","github-profile","metrics","readme-profile","readme-template"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leonardokr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T13:08:11.000Z","updated_at":"2026-02-13T12:00:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leonardokr/leo-git-statistics","commit_stats":null,"previous_names":["leonardokr/leo-git-statistics"],"tags_count":14,"template":true,"template_full_name":null,"purl":"pkg:github/leonardokr/leo-git-statistics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonardokr%2Fleo-git-statistics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonardokr%2Fleo-git-statistics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonardokr%2Fleo-git-statistics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonardokr%2Fleo-git-statistics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leonardokr","download_url":"https://codeload.github.com/leonardokr/leo-git-statistics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonardokr%2Fleo-git-statistics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29640861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T03:21:14.183Z","status":"ssl_error","status_checked_at":"2026-02-20T03:18:24.455Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github","github-actions","github-api","github-profile","metrics","readme-profile","readme-template"],"created_at":"2026-02-13T05:53:51.712Z","updated_at":"2026-02-20T04:00:58.501Z","avatar_url":"https://github.com/leonardokr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/overview_sample_light.svg\" alt=\"GitHub Stats Overview\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eLeo's Git Statistics\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eGenerate beautiful, customizable SVG statistics cards for your GitHub profile\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e •\n  \u003ca href=\"#themes\"\u003eThemes\u003c/a\u003e •\n  \u003ca href=\"#quick-start\"\u003eQuick Start\u003c/a\u003e •\n  \u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e •\n  \u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Features\n\n- **Multiple Statistics Cards** - Overview stats, language distribution, contribution streaks, streak battery, language puzzle, and weekly commit calendar\n- **25+ Built-in Themes** - From Dracula to Nord, Catppuccin to Tokyo Night\n- **Extensible Theme System** - Add your own themes via YAML files\n- **Animated SVGs** - Smooth fade-in and slide animations\n- **Fully Configurable** - Control which stats to show, filter repositories, and more\n- **Reusable GitHub Action** - Run the generator from any repository (great for profile repos)\n- **Accumulated Metrics** - Track views and clones beyond GitHub's 14-day limit\n- **REST API** - Access all statistics data as JSON for portfolios and web applications (requires backend hosting)\n\n## Generated Cards\n\n### Overview Statistics\nDisplays comprehensive GitHub statistics including contributions, repositories, stars, forks, and more.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/overview_sample_dark.svg\" alt=\"Overview Dark Mode\" width=\"49%\" /\u003e\n  \u003cimg src=\"generated_images/samples/overview_sample_light.svg\" alt=\"Overview Light Mode\" width=\"49%\" /\u003e\n\u003c/p\u003e\n\n### Language Distribution\nShows your most used programming languages with an animated progress bar.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/languages_sample_dark.svg\" alt=\"Languages Dark Mode\" width=\"49%\" /\u003e\n  \u003cimg src=\"generated_images/samples/languages_sample_light.svg\" alt=\"Languages Light Mode\" width=\"49%\" /\u003e\n\u003c/p\u003e\n\n### Contribution Streak\nTracks your current and longest contribution streaks.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/streak_sample_dark.svg\" alt=\"Streak Dark Mode\" width=\"49%\" /\u003e\n  \u003cimg src=\"generated_images/samples/streak_sample_light.svg\" alt=\"Streak Light Mode\" width=\"49%\" /\u003e\n\u003c/p\u003e\n\n### Streak Battery\nVisual battery indicator showing your streak progress with recent contribution history.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/streak_battery_sample_dark.svg\" alt=\"Streak Battery Dark Mode\" width=\"49%\" /\u003e\n  \u003cimg src=\"generated_images/samples/streak_battery_sample_light.svg\" alt=\"Streak Battery Light Mode\" width=\"49%\" /\u003e\n\u003c/p\u003e\n\n### Language Puzzle\nTreemap visualization of your programming languages - area proportional to usage percentage.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/languages_puzzle_sample_dark.svg\" alt=\"Language Puzzle Dark Mode\" width=\"49%\" /\u003e\n  \u003cimg src=\"generated_images/samples/languages_puzzle_sample_light.svg\" alt=\"Language Puzzle Light Mode\" width=\"49%\" /\u003e\n\u003c/p\u003e\n\n### Weekly Commit Calendar\nAgenda-style weekly calendar where each commit is a time block, with repositories separated by color.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/commit_calendar_sample_dark.svg\" alt=\"Commit Calendar Dark Mode\" width=\"98%\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"generated_images/samples/commit_calendar_sample_light.svg\" alt=\"Commit Calendar Light Mode\" width=\"98%\" /\u003e\n\u003c/p\u003e\n\n## Themes\n\nChoose from **25+ built-in themes** or create your own:\n\n| Category | Themes |\n|----------|--------|\n| **GitHub** | `default`, `light`, `dark`, `github_dimmed` |\n| **Popular** | `dracula`, `nord`, `gruvbox`, `gruvbox_light`, `one_dark`, `monokai`, `tokyo_night`, `solarized_dark`, `solarized_light` |\n| **Catppuccin** | `catppuccin_latte`, `catppuccin_frappe`, `catppuccin_macchiato`, `catppuccin_mocha` |\n| **Material** | `palenight`, `material_darker`, `material_ocean`, `ayu`, `ayu_light`, `ayu_mirage` |\n| **Creative** | `synthwave`, `cyberpunk`, `ocean`, `forest`, `sunset`, `midnight`, `aurora`, `neon`, `retro`, `lavender`, `rose_pine`, `rose_pine_dawn` |\n\n### Theme Previews\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eDracula\u003c/b\u003e\u003c/summary\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/overview_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"49%\" /\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/streak_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/streak_battery_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_puzzle_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/commit_calendar_sample_dracula.svg\" alt=\"Dracula Theme\" width=\"98%\" /\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eNord\u003c/b\u003e\u003c/summary\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/overview_sample_nord.svg\" alt=\"Nord Theme\" width=\"49%\" /\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/streak_sample_nord.svg\" alt=\"Nord Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/streak_battery_sample_nord.svg\" alt=\"Nord Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_sample_nord.svg\" alt=\"Nord Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_puzzle_sample_nord.svg\" alt=\"Nord Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/commit_calendar_sample_nord.svg\" alt=\"Nord Theme\" width=\"98%\" /\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eTokyo Night\u003c/b\u003e\u003c/summary\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/overview_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"49%\" /\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/streak_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/streak_battery_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_puzzle_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/commit_calendar_sample_tokyo_night.svg\" alt=\"Tokyo Night Theme\" width=\"98%\" /\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eCatppuccin Mocha\u003c/b\u003e\u003c/summary\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/overview_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"49%\" /\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"generated_images/samples/streak_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/streak_battery_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/languages_puzzle_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"49%\" /\u003e\n\u003cimg src=\"generated_images/samples/commit_calendar_sample_catppuccin_mocha.svg\" alt=\"Catppuccin Mocha Theme\" width=\"98%\" /\u003e\n\u003c/div\u003e\n\u003c/details\u003e\n\n## Quick Start\n\n### 1. Choose How You Want to Use It\n- Recommended: call this repository as a reusable GitHub Action from your profile repository.\n- Use **Use this template** only when you need advanced customization not exposed by action inputs (for example: editing generators, templates, themes source files, architecture, or custom business rules).\n\n### 2. Create a Personal Access Token\n1. Go to **Settings** -\u003e **Developer settings** -\u003e **Personal access tokens** -\u003e **Tokens (classic)**\n2. Generate a new token with scopes: `repo`, `read:user`, `read:org`\n3. Copy the token\n\n### 3. Add Repository Secret\n1. In your profile repository (`\u003cusername\u003e/\u003cusername\u003e`): **Settings** -\u003e **Secrets and variables** -\u003e **Actions**\n2. Create secret named `PROFILE_STATS_TOKEN` with your token\n\n### 4. Add a Workflow in Your Profile Repository\nUse this action from your profile repository workflow:\n\n```yaml\n- name: Generate profile SVG stats\n  uses: leonardokr/leo-git-statistics@v1\n  with:\n    github-token: ${{ secrets.PROFILE_STATS_TOKEN }}\n    github-username: leonardokr\n    output-dir: profile\n```\n\n### 5. Configure (Optional)\nPass optional `with:` inputs in your profile workflow (see full list below in **Workflow Configuration (Profile Repository)**).\n\n## Workflow Configuration (Profile Repository)\n\nUse this repository as an Action in your profile repository. This is the recommended path for most users.\n\nRequired secret in your profile repository:\n\n- `PROFILE_STATS_TOKEN`: token used by `generate.py` to query GitHub APIs.\n\n### Example Workflow (profile repository)\n\n```yaml\nname: Update Profile SVG Stats\n\non:\n  schedule:\n    - cron: \"0 */12 * * *\"\n  workflow_dispatch:\n\npermissions:\n  contents: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout profile repository\n        uses: actions/checkout@v4\n\n      - name: Generate SVGs via leo-git-statistics action\n        uses: leonardokr/leo-git-statistics@v1\n        with:\n          github-token: ${{ secrets.PROFILE_STATS_TOKEN }}\n          github-username: leonardokr\n          output-dir: profile\n          themes: dark,light\n          excluded-repos: owner/repo1,owner/repo2\n          exclude-archive-repos: \"true\"\n          show-stars: \"true\"\n          show-issues: \"false\"\n\n      - name: Keep README-friendly filenames\n        run: |\n          cp profile/overviewdark.svg profile/stats.svg\n          cp profile/languagesdark.svg profile/top-langs.svg\n\n      - name: Commit and push\n        run: |\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"github-actions[bot]@users.noreply.github.com\"\n          git add profile/*.svg\n          if ! git diff --quiet --staged; then\n            git commit -m \"chore(stats): update profile SVG stats\"\n            git push\n          fi\n```\n\n### Action Inputs (`with:`)\n\n| Input                      | Required | Default                    | Description                                              |\n| ----------------------------| ----------| ----------------------------| ----------------------------------------------------------|\n| `github-token`             | Yes      | -                          | GitHub token consumed as `ACCESS_TOKEN`.                 |\n| `github-username`          | No       | `github.actor`             | GitHub user to collect stats for.                        |\n| `python-version`           | No       | `3.11`                     | Python runtime version.                                  |\n| `output-dir`               | No       | `generated_images`         | Destination folder in caller repository.                 |\n| `themes`                   | No       | from `config.yml`          | Comma-separated themes (example: `dark,light`) or `all`. |\n| `timezone`                 | No       | from `config.yml` or `UTC` | IANA timezone (example: `America/Sao_Paulo`).            |\n| `excluded-repos`           | No       | from `config.yml`          | Comma-separated repos to exclude.                        |\n| `excluded-langs`           | No       | from `config.yml`          | Comma-separated languages to exclude.                    |\n| `include-forked-repos`     | No       | from `config.yml`          | `true` or `false`.                                       |\n| `exclude-contrib-repos`    | No       | from `config.yml`          | `true` or `false`.                                       |\n| `exclude-archive-repos`    | No       | from `config.yml`          | `true` or `false`.                                       |\n| `exclude-private-repos`    | No       | from `config.yml`          | `true` or `false`.                                       |\n| `exclude-public-repos`     | No       | from `config.yml`          | `true` or `false`.                                       |\n| `store-repo-views`         | No       | from `config.yml`          | `true` or `false`.                                       |\n| `store-repo-clones`        | No       | from `config.yml`          | `true` or `false`.                                       |\n| `more-collabs`             | No       | from `config.yml`          | Integer to manually add collaborator count.              |\n| `manually-added-repos`     | No       | from `config.yml`          | Comma-separated `owner/repo` list to include.            |\n| `only-included-repos`      | No       | from `config.yml`          | If set, only these `owner/repo` entries are used.        |\n| `show-total-contributions` | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-repositories`        | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-lines-changed`       | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-avg-percent`         | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-collaborators`       | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-contributors`        | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-views`               | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-clones`              | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-forks`               | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-stars`               | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-pull-requests`       | No       | from `config.yml`          | `true` or `false`.                                       |\n| `show-issues`              | No       | from `config.yml`          | `true` or `false`.                                       |\n\n## Repository Configuration (config.yml)\n\nThis section is for repository-level configuration in `config.yml` (mainly for template/advanced customization). For normal usage via Action, prefer workflow `with:` inputs shown below.\n\n### Theme Selection\n\n```yaml\nthemes:\n  enabled:\n    - default\n    - dark\n    - dracula\n    - nord\n    # Use 'all' to generate all themes\n```\n\n### Repository Filters\n\n```yaml\nstats_generation:\n  excluded_repos: \"repo1,repo2\"\n  excluded_langs: \"HTML,CSS\"\n  include_forked_repos: \"false\"\n  exclude_private_repos: \"false\"\n  exclude_archive_repos: \"true\"\n```\n\n### Statistics Visibility\n\n```yaml\nstats_generation:\n  show_total_contributions: \"true\"\n  show_repositories: \"true\"\n  show_lines_changed: \"true\"\n  show_stars: \"true\"\n  show_pull_requests: \"true\"\n  # ... more options\n```\n\n## Versioning and Releases\n\nThis repository uses automated releases with `release-please` on `main`.\n\n- Create changes in branches and merge with Conventional Commits.\n- `release-please` opens/updates a release PR with changelog entries.\n- When the release PR is merged, it creates a GitHub Release and a semver tag (`v1.2.3`).\n- The workflow also updates the floating major tag (`v1`, `v2`, ...) to the latest patch/minor of that major.\n\nFor consumers:\n\n- Use `@v1` for stable major updates with automatic minor/patch refreshes.\n- Pin exact versions (`@v1.2.3`) only when strict reproducibility is required.\n## Creating Custom Themes\n\nAdd a new `.yml` file in `src/themes/`:\n\n```yaml\n# src/themes/my_theme.yml\nmy_awesome_theme:\n  suffix: \"MyAwesome\"\n  colors:\n    bg_color: \"#1a1b26\"\n    title_color: \"#7aa2f7\"\n    text_color: \"#a9b1d6\"\n    icon_color: \"#bb9af7\"\n    percent_color: \"#565f89\"\n    border_color: \"#292e42\"\n    accent_color: \"#9ece6a\"\n    gradient_start: \"#7aa2f7\"\n    gradient_end: \"#bb9af7\"\n```\n\nThen enable it in `config.yml`:\n\n```yaml\nthemes:\n  enabled:\n    - my_awesome_theme\n```\n\n## REST API\n\nThis project also provides a **REST API** that exposes all statistics data as JSON. Perfect for portfolios, dashboards, and web applications.\n\n\u003e **Note:** The API is a Flask application that requires backend hosting (Render, Railway, PythonAnywhere, etc.). It cannot run on GitHub Pages.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eClick to view API Documentation\u003c/b\u003e\u003c/summary\u003e\n\n### Quick Start\n\n```bash\n# 1. Install dependencies\npip install -r requirements.txt\n\n# 2. Configure environment (see api/.env.example)\nexport GITHUB_TOKEN=your_token_here\n\n# 3. Run the API\npython api/app.py\n\n# 4. Access interactive docs at http://localhost:5000/docs\n```\n\n### Key Endpoints\n\n| Endpoint                                             | Description                  |\n| ------------------------------------------------------| ------------------------------|\n| `GET /users/{username}/overview`              | Complete overview statistics |\n| `GET /users/{username}/languages`             | Language distribution        |\n| `GET /users/{username}/repositories`          | Repository list (names only) |\n| `GET /users/{username}/repositories/detailed` | Detailed repository info     |\n| `GET /users/{username}/streak`                | Contribution streak data     |\n| `GET /users/{username}/stats/full`            | All data in one request      |\n\n### Example Response\n\n```bash\ncurl http://localhost:5000/users/leonardokr/overview\n```\n\n```json\n{\n  \"username\": \"leonardokr\",\n  \"name\": \"Leonardo Klein\",\n  \"total_contributions\": 1250,\n  \"repositories_count\": 42,\n  \"total_stars\": 320,\n  \"total_forks\": 45,\n  \"lines_added\": 45230,\n  \"lines_deleted\": 12340,\n  \"avg_contribution_percent\": \"68.50%\"\n}\n```\n\n### Interactive Documentation\n\nThe API includes **Swagger/OpenAPI** documentation. After running the API, visit:\n\n```\nhttp://localhost:5000/docs\n```\n\nYou'll see an interactive interface where you can test all endpoints directly in your browser.\n\n### Deployment Options\n\nThe API needs a backend platform that supports Python:\n\n#### Recommended: Render (Free)\n1. Create account at [render.com](https://render.com)\n2. New → Web Service → Connect GitHub repo\n3. Configure:\n   - Build: `pip install -r requirements.txt`\n   - Start: `python api/app.py`\n   - Environment variable: `GITHUB_TOKEN=your_token`\n4. Deploy!\n\n**Other Options:**\n- **Railway** - $5 credit/month free tier\n- **PythonAnywhere** - 1 free web app, always running\n- **Fly.io** - 3 free VMs with limits\n\n#### Using with Static Sites (GitHub Pages)\n\nFor static portfolios, generate JSON files via GitHub Actions.\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to view static API generation guide\u003c/summary\u003e\n\n**Generate Static JSON Files**\n\nUse the `api/generate_static_api.py` script to create static JSON files for all endpoints:\n\n```bash\nexport GITHUB_TOKEN=your_token\nexport GITHUB_ACTOR=your_username\npython api/generate_static_api.py\n```\n\nThis creates:\n```\napi-data/\n└── users/\n    └── {username}/\n        ├── overview.json\n        ├── languages.json\n        ├── streak.json\n        ├── repositories.json\n        └── stats-full.json\n```\n\n**Deploy with GitHub Actions**\n\nCreate `.github/workflows/generate-api-data.yml`:\n\n```yaml\nname: Generate Static API Data\n\non:\n  schedule:\n    - cron: \"0 */6 * * *\"  # Every 6 hours\n  workflow_dispatch:\n\npermissions:\n  contents: write\n\njobs:\n  generate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.11\"\n\n      - name: Install dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt\n\n      - name: Generate static API JSON files\n        env:\n          ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          GITHUB_ACTOR: ${{ github.repository_owner }}\n        run: python api/generate_static_api.py\n\n      - name: Deploy to GitHub Pages\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./api-data\n          publish_branch: gh-pages\n          destination_dir: api\n```\n\nThen access: `https://username.github.io/repo/api/users/username/overview.json`\n\n\u003c/details\u003e\n\n### Portfolio Integration Example\n\n**Option 1: Client-side fetch (hosted API)**\n```javascript\n// In your portfolio site (e.g., leonardokr.github.io)\nfetch('https://your-api.onrender.com/users/leonardokr/repositories/detailed')\n  .then(res =\u003e res.json())\n  .then(data =\u003e {\n    // Render projects with full details\n    data.repositories.forEach(repo =\u003e {\n      renderProject(repo); // repo has name, description, stars, topics, etc.\n    });\n  });\n```\n\n**Option 2: Build-time generation (GitHub Actions)**\n```yaml\n# In your portfolio repository workflow\n- name: Fetch latest projects\n  run: |\n    curl https://your-api.onrender.com/users/leonardokr/repositories/detailed \\\n      -o src/data/projects.json\n\n- name: Build site with fresh data\n  run: npm run build\n```\n\n**Option 3: Static JSON files (no backend needed)**\n- Generate JSON files via GitHub Actions in this repo\n- Deploy to `gh-pages` branch\n- Your portfolio fetches: `https://username.github.io/leo-git-statistics/api/users/username/repositories.json`\n\n### Usage Examples\n\n**JavaScript (Fetch)**\n```javascript\n// Get all stats\nconst response = await fetch('https://api.example.com/users/leonardokr/stats/full');\nconst stats = await response.json();\n\n// Get only repositories\nconst repos = await fetch('https://api.example.com/users/leonardokr/repositories');\nconst data = await repos.json();\nconsole.log(data.repositories); // Array of repo names\n```\n\n**Python**\n```python\nimport requests\n\n# Get overview\nstats = requests.get('https://api.example.com/users/leonardokr/overview').json()\nprint(f\"Total stars: {stats['total_stars']}\")\n\n# Get languages\nlangs = requests.get('https://api.example.com/users/leonardokr/languages').json()\nprint(langs['languages'])\n```\n\n**cURL**\n```bash\n# Get repositories for portfolio\ncurl https://api.example.com/users/leonardokr/repositories\n\n# Get full stats\ncurl https://api.example.com/users/leonardokr/stats/full\n```\n\n### Environment Variables\n\nCreate `api/.env` file (see `api/.env.example`):\n\n```bash\n# Required\nGITHUB_TOKEN=your_github_personal_access_token\n\n# Optional\nPORT=5000\nFLASK_DEBUG=false\nAPI_HOST=localhost:5000\n```\n\n### CORS\n\nCORS is enabled for all origins by default. To restrict, edit `api/app.py`:\n\n```python\nCORS(app, origins=[\"https://leonardokr.github.io\"])\n```\n\n### Rate Limits\n\n- **Authenticated:** 5000 requests/hour (with `GITHUB_TOKEN`)\n- **Unauthenticated:** 60 requests/hour\n\nAlways use a token to avoid limits.\n\n\u003c/details\u003e\n\n## Architecture\n\n```\nleo-git-statistics/\n├── generate.py                          # Main SVG generation script\n├── requirements.txt                     # Python dependencies\n├── config.yml                           # Configuration file\n├── .env.example                         # Environment variables example\n├── api/                                 # REST API\n│   ├── app.py                           # Flask API application\n│   ├── generate_static_api.py           # Static JSON generator for GitHub Pages\n│   └── .env.example                     # API environment variables\n├── src/                                 # Core business logic\n│   ├── core/                            # Domain logic \u0026 data collection\n│   │   ├── config.py                    # Theme configuration management\n│   │   ├── credentials.py               # GitHub token/actor resolution\n│   │   ├── environment.py               # Environment variables \u0026 injectable dependencies\n│   │   ├── display_settings.py          # Statistics visibility toggles\n│   │   ├── repository_filter.py         # Repository inclusion/exclusion rules\n│   │   ├── traffic_stats.py             # Accumulated traffic state\n│   │   ├── protocols.py                 # Segregated Protocol interfaces (ISP)\n│   │   ├── github_client.py             # GitHub API client (GraphQL + REST)\n│   │   ├── graphql_queries.py           # GraphQL query builders\n│   │   ├── stats_collector.py           # Facade composing all collectors\n│   │   ├── repo_stats_collector.py      # Repos, stars, forks, languages\n│   │   ├── contribution_tracker.py      # Streaks \u0026 contribution calendar\n│   │   ├── commit_schedule_collector.py # Weekly commit schedule by repository\n│   │   ├── code_change_analyzer.py      # Lines changed, percentages, contributors\n│   │   ├── traffic_collector.py         # Views \u0026 clones traffic\n│   │   ├── engagement_collector.py      # Pull requests, issues, collaborators\n│   │   └── mock_stats.py                # Mock data for local testing\n│   ├── db/                              # Data persistence\n│   │   └── db.py                        # JSON database for accumulated metrics\n│   ├── generators/                      # SVG generators (auto-discovered via registry)\n│   │   ├── base.py                      # BaseGenerator ABC + GeneratorRegistry\n│   │   ├── overview.py                  # Overview statistics card\n│   │   ├── languages.py                 # Language distribution card\n│   │   ├── languages_puzzle.py          # Language treemap card\n│   │   ├── streak.py                    # Contribution streak card\n│   │   ├── streak_battery.py            # Streak battery card\n│   │   └── commit_calendar.py           # Weekly commit calendar card\n│   ├── presentation/                    # Rendering layer\n│   │   ├── stats_formatter.py           # Data formatting utilities\n│   │   ├── svg_template.py              # SVG template engine\n│   │   └── visual_algorithms.py         # Treemap \u0026 color palette algorithms\n│   ├── templates/                       # SVG templates\n│   │   ├── overview.svg\n│   │   ├── languages.svg\n│   │   ├── languages_puzzle.svg\n│   │   ├── streak.svg\n│   │   ├── streak_battery.svg\n│   │   └── commit_calendar.svg\n│   ├── themes/                          # Theme definitions (YAML)\n│   │   ├── loader.py                    # Theme loading utilities\n│   │   ├── github.yml\n│   │   ├── popular.yml\n│   │   ├── catppuccin.yml\n│   │   ├── material.yml\n│   │   └── creative.yml\n│   ├── utils/                           # Utility functions\n│   │   ├── file_system.py               # File system helpers\n│   │   ├── decorators.py                # Async property decorators\n│   │   └── helpers.py                   # Shared helper functions\n│   └── orchestrator.py                  # Main coordinator\n├── examples/                            # Integration examples\n│   └── portfolio-integration.md         # Complete portfolio integration guide\n└── test/                                # Unit tests\n```\n\n### Key Design Decisions\n\n- **SOLID Architecture** - Each class has a single responsibility, dependencies are injected, and interfaces are segregated via `typing.Protocol`\n- **Facade Pattern** - `StatsCollector` composes 6 specialized collectors (`RepoStatsCollector`, `ContributionTracker`, `CommitScheduleCollector`, `CodeChangeAnalyzer`, `TrafficCollector`, `EngagementCollector`) behind a unified API\n- **Registry Pattern** - Generators self-register via `@register_generator` decorator; the orchestrator discovers them automatically without hardcoded lists\n- **Protocol-based Interfaces** - Each generator depends only on the subset of stats it needs (`StreakProvider`, `LanguageProvider`, `OverviewProvider`, `BatteryProvider`, `CommitCalendarProvider`)\n- **Dependency Injection** - All major classes accept optional dependencies in their constructors for testability\n- **Async/Await** - Concurrent API calls for better performance\n- **YAML-based Themes** - Easy to add, remove, or modify themes\n- **Template Engine** - Simple placeholder replacement for maintainability\n- **Persistent Storage** - JSON database for accumulated metrics beyond GitHub's 14-day limit\n\n## Development\n\n### Prerequisites\n- Python 3.10+\n- pip\n\n### Setup\n\n```bash\npip install -r requirements.txt\n```\n\n### Running Locally\n\n#### With GitHub API (real data)\n\n```bash\nexport ACCESS_TOKEN=\"your_github_token\"\nexport GITHUB_ACTOR=\"your_username\"\npython generate.py\n```\n\n#### With Mock Data (no API required)\n\nFor testing templates, themes, and visual changes without needing a GitHub token:\n\n```bash\npython generate_test.py\n```\n\nThis generates all SVG cards using mock data in the `generated_images/` folder. Useful for:\n- Testing theme modifications\n- Developing new SVG templates\n- Previewing visual changes locally\n- CI/CD pipelines without API access\n\n### Running Tests\n\n```bash\npytest test/\n```\n\n## Contributing\n\nContributions are welcome! Feel free to:\n\n- Add new themes\n- Improve SVG templates\n- Add new statistics\n- Fix bugs\n- Improve documentation\n\n## License\n\nGPL-3.0 License - see [LICENSE](LICENSE) for details.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eBuilt with Python and GitHub Actions\u003c/sub\u003e\n\u003c/p\u003e\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonardokr%2Fleo-git-statistics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleonardokr%2Fleo-git-statistics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonardokr%2Fleo-git-statistics/lists"}