{"id":47277012,"url":"https://github.com/readme-svg/contribution-painter","last_synced_at":"2026-04-01T17:48:24.887Z","repository":{"id":344147335,"uuid":"1180653681","full_name":"readme-SVG/Contribution-Painter","owner":"readme-SVG","description":"🥑 Paint pixel-art on your GitHub contribution graph via backdated commits. Static frontend + GitHub API.","archived":false,"fork":false,"pushed_at":"2026-03-13T19:54:00.000Z","size":2934,"stargazers_count":3,"open_issues_count":9,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-16T05:39:59.259Z","etag":null,"topics":["contribution","contribution-heatmap","git-automation","github-actions","github-api","github-contribution-graph","github-page","github-pages","graph","graph-algorithms","graph-art","i18n","pixel-art","python","vanilla-javascript"],"latest_commit_sha":null,"homepage":"https://readme-svg.github.io/Contribution-Painter/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/readme-SVG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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},"funding":{"patreon":"OstinFCT","ko_fi":"fctostin","custom":["https://boosty.to/ostinfct","https://t.me/FCTostin","https://www.youtube.com/@FCT-Ostin"],"github":"OstinUA"}},"created_at":"2026-03-13T09:11:14.000Z","updated_at":"2026-03-14T03:26:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/readme-SVG/Contribution-Painter","commit_stats":null,"previous_names":["readme-svg/graph-art-generator"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/readme-SVG/Contribution-Painter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/readme-SVG%2FContribution-Painter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/readme-SVG%2FContribution-Painter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/readme-SVG%2FContribution-Painter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/readme-SVG%2FContribution-Painter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/readme-SVG","download_url":"https://codeload.github.com/readme-SVG/Contribution-Painter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/readme-SVG%2FContribution-Painter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30631420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: 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":["contribution","contribution-heatmap","git-automation","github-actions","github-api","github-contribution-graph","github-page","github-pages","graph","graph-algorithms","graph-art","i18n","pixel-art","python","vanilla-javascript"],"created_at":"2026-03-15T19:20:58.455Z","updated_at":"2026-03-17T21:01:14.629Z","avatar_url":"https://github.com/readme-SVG.png","language":"JavaScript","readme":"![Contribution Painter](https://raw.githubusercontent.com/readme-SVG/Contribution-Painter/main/images/contribution_painter_loop.svg)\n\n\u003e Turn your GitHub contribution graph into pixel-art by generating backdated commits from a web UI.\n\n[![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue?style=for-the-badge)](LICENSE)\n[![Python](https://img.shields.io/badge/Python-3.11%2B-3776AB?style=for-the-badge\u0026logo=python\u0026logoColor=white)](requirements.txt)\n[![Frontend](https://img.shields.io/badge/Frontend-Vanilla%20JS-323330?style=for-the-badge\u0026logo=javascript)](js/app.js)\n[![Deploy](https://img.shields.io/badge/Deploy-Vercel-000000?style=for-the-badge\u0026logo=vercel)](vercel.json)\n[![Workflow](https://img.shields.io/badge/GitHub%20Actions-AI%20Issue%20Generator-2088FF?style=for-the-badge\u0026logo=githubactions)](.github/workflows/ai-issue.yml)\n\n## Table of Contents\n\n- [Features](#features)\n- [Technology Stack](#technology-stack)\n- [Technical Block](#technical-block)\n  - [Project Structure](#project-structure)\n  - [Key Design Decisions](#key-design-decisions)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n- [Testing](#testing)\n- [Deployment](#deployment)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [License](#license)\n- [Contacts](#contacts)\n\n## Features\n\nContribution Painter is built for devs who want deterministic control over contribution heatmaps without touching heavy frameworks.\n\n- Interactive GitHub-style yearly heatmap editor with drag-to-paint controls.\n- Intensity model (`0..4`) + commit multiplier (`x1/x3/x5/x10`) for fast density scaling.\n- Year selection across current, previous, and next years with automatic week-grid alignment.\n- Keyboard shortcuts (`0..4`) for instant palette switching.\n- Graph operations: clear canvas, fill all active cells, invert paint state.\n- Real-time stats: painted days, estimated commit count, and active period boundaries.\n- Direct GitHub REST API push pipeline that writes git blobs, trees, commits, and branch refs.\n- Supports creating a new branch if the target branch does not exist.\n- Multi-language UI via pluggable i18n dictionaries.\n- Progress bar + live logs for long-running commit generation jobs.\n- Vercel-ready static deployment config.\n- AI-driven GitHub Action that analyzes code changes and opens structured issues.\n\n\u003e [!IMPORTANT]\n\u003e The tool creates real commits in your repository history. Use it only in repos where rewritten contribution history is acceptable.\n\n## Technology Stack\n\n### Core\n- `HTML5` for the single-page UI shell.\n- `CSS3` for GitHub-like contribution graph styling.\n- `Vanilla JavaScript` for editor state, i18n, and GitHub API integration.\n\n### Backend Automation\n- `Python 3.11+` for GitHub Action automation script.\n- `PyGithub`, `requests`, `python-dotenv` for GitHub and model API orchestration.\n\n### DevOps / Infra\n- `GitHub Actions` for automated push/PR analysis.\n- `Vercel` static hosting config for frontend deployment.\n\n## Technical Block\n\n### Project Structure\n\n```text\n.\n├── index.html                     # Main web app entrypoint\n├── css/styles.css               # UI styles\n├── js/\n│   ├── app.js                     # Painter logic + GitHub API workflow\n│   └── i18n/*.js                  # Localization dictionaries\n├── process_event.py               # AI-powered GitHub issue generator workflow script\n├── .github/\n│   ├── workflows/ai-issue.yml     # CI workflow invoking automation script\n│   ├── ISSUE_TEMPLATE/            # Bug/feature templates\n│   └── pull_request_template.md   # PR checklist template\n├── requirements.txt               # Python dependencies for automation\n├── vercel.json                    # Static hosting routing and headers\n└── LICENSE                        # GPL-3.0 license\n```\n\n### Key Design Decisions\n\n- Frontend is framework-free by design: lower bundle complexity, easier self-hosting, and easy auditability.\n- Commits are generated via low-level Git Data API (`blobs/trees/commits/refs`) to allow exact commit timestamp control.\n- The contribution editor maps to a week-column x weekday-row matrix to mirror GitHub contribution graph semantics.\n- i18n dictionaries are split per locale to keep translation churn isolated and avoid monolithic translation files.\n- CI analysis is decoupled from frontend runtime; automation lives in Python to leverage mature GitHub SDK ergonomics.\n\n## Getting Started\n\n### Prerequisites\n\nInstall these tools first:\n\n- `git`\n- `Python 3.11+`\n- `pip`\n- Optional for frontend local dev convenience: `python -m http.server` or any static file server\n- A GitHub personal access token with `repo` scope for writing commits\n\n\u003e [!TIP]\n\u003e For testing safely, create a throwaway repository with a single seed commit (`README.md`) before pushing generated history.\n\n### Installation\n\n```bash\n# 1) Clone repository\ngit clone https://github.com/readme-SVG/Contribution-Painter.git\ncd Contribution-Painter\n\n# 2) Set up Python environment (for automation script and local checks)\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\n# 3) Run a local static server for the frontend\npython3 -m http.server 8080\n\n# 4) Open in browser\n# http://localhost:8080\n```\n\n## Testing\n\nThis project is lightweight and does not currently ship with a formal unit/integration test suite. You can still run practical validation checks.\n\n```bash\n# Python syntax check for backend automation\npython3 -m py_compile process_event.py\n\n# Optional: quick dependency sanity\npython3 -m pip check\n\n# Optional: run script help/debug in controlled env\n# (requires env vars like GITHUB_TOKEN, GH_MODELS_TOKEN)\npython3 process_event.py\n```\n\n\u003e [!WARNING]\n\u003e Running `process_event.py` without required environment variables will fail by design.\n\n## Deployment\n\n### Frontend (Vercel)\n\nThe repository includes `vercel.json` for static deployment with SPA-style route fallback.\n\n```bash\n# Option A: Vercel CLI\nnpm i -g vercel\nvercel\n\n# Option B: connect repo in Vercel dashboard\n# Vercel will serve index.html and route all paths back to it.\n```\n\n### CI/CD (GitHub Actions)\n\n- On pushes to `main` and PR events, `ai-issue.yml` runs the Python analyzer.\n- The workflow checks out code, installs Python, installs dependencies, and executes analysis script.\n\n\u003e [!CAUTION]\n\u003e Ensure secrets (`GH_MODELS_TOKEN`, optional `ALLOWED_USER`) are configured before enabling the workflow in production repos.\n\n## Usage\n\nUse the web UI to paint days and push generated commits.\n\n```text\n# 1. Open app in browser.\n# 2. Fill in:\n#    - GitHub Token (repo scope)\n#    - Repository: \u003cowner\u003e/\u003crepo\u003e\n#    - Email: exactly matching GitHub account email\n#    - Git name and branch (optional, defaults to main)\n# 3. Pick year + intensity + multiplier.\n# 4. Paint graph cells with mouse (or hit keys 0-4 to switch levels).\n# 5. Click \"Push to GitHub\" and monitor progress/log output.\n```\n\nExample local run:\n\n```bash\npython3 -m http.server 8080\n# then visit http://localhost:8080 and execute push from UI\n```\n\n## Configuration\n\n### UI Runtime Inputs\n\n- `GitHub Token` (`repo` scope required for commit/branch writes)\n- `Repository` (`owner/repo`)\n- `Email` (must match GitHub account email for contribution graph attribution)\n- `Name` (commit author/committer display name)\n- `Branch` (target branch, created automatically when missing)\n- `Commit multiplier` (scales commit volume per painted intensity)\n- `Year` (drives graph date range)\n\n### Workflow Environment Variables (for `process_event.py`)\n\n- `GITHUB_TOKEN` – GitHub Actions token used by workflow.\n- `REPOSITORY` – target repository identifier.\n- `EVENT_NAME` – event type (`push`, `pull_request`, etc.).\n- `COMMIT_SHA` – commit hash for push context.\n- `PR_NUMBER` – PR number when running in PR context.\n- `GH_MODELS_TOKEN` – token for model endpoint authentication.\n- `ALLOWED_USER` – optional actor gate for execution.\n\n## License\n\nDistributed under the `GPL-3.0` license. See [`LICENSE`](LICENSE) for full legal text.\n\n## Contacts\n\n## ❤️ Support the Project\n\n[![Patreon](https://img.shields.io/badge/Patreon-OstinFCT-f96854?style=flat-square\u0026logo=patreon)](https://www.patreon.com/OstinFCT)\n[![Ko-fi](https://img.shields.io/badge/Ko--fi-fctostin-29abe0?style=flat-square\u0026logo=ko-fi)](https://ko-fi.com/fctostin)\n[![Boosty](https://img.shields.io/badge/Boosty-Support-f15f2c?style=flat-square)](https://boosty.to/ostinfct)\n[![YouTube](https://img.shields.io/badge/YouTube-FCT--Ostin-red?style=flat-square\u0026logo=youtube)](https://www.youtube.com/@FCT-Ostin)\n[![Telegram](https://img.shields.io/badge/Telegram-FCTostin-2ca5e0?style=flat-square\u0026logo=telegram)](https://t.me/FCTostin)\n\nIf you find this tool useful, consider leaving a ⭐ on GitHub or supporting the author directly.\n","funding_links":["https://patreon.com/OstinFCT","https://ko-fi.com/fctostin","https://boosty.to/ostinfct","https://t.me/FCTostin","https://www.youtube.com/@FCT-Ostin","https://github.com/sponsors/OstinUA","https://www.patreon.com/OstinFCT"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freadme-svg%2Fcontribution-painter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freadme-svg%2Fcontribution-painter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freadme-svg%2Fcontribution-painter/lists"}