Displays a calendar heat map of GitHub contributions (demo, static demo).
If the request is made to the frontend base URL, it will show the contributions for the user currently logged into GitHub. If there is a username after the base URL, it will show the contributions for that GitHub user.
- Authenticated. This is the default mode that requires the user to be
authenticated with GitHub in order to see data. Handled by
index.html(demo). - Static. The same interfaces as authenticated mode, but it loads the data
from a file on the server (generated by
scripts/generate-static.ts). Handled bystatic.html(demo). - Compact. Suitable for embedding in another page. This just shows the heat
map without the repository list or the pop-overs. Handled by
compact.html(demo).
Configuration of the frontend is via environment variables when running
deno run dev or deno run build:
VITE_GITHUB_CLIENT_ID: The GitHub client ID for this app (from GitHub app settings).VITE_FRONTEND_URL: The app’s homepage (needs to match GitHub app settings).VITE_BACKEND_URL: Defaults to$VITE_FRONTEND_URL. This is the URL prefix for API calls, e.g.$VITE_BACKEND_URL/api/health. Note that the default backend (inbackend/) does not support Cross-Origin Resource Sharing, so usually this cannot reference a different host than$VITE_FRONTEND_URL. It doesn’t have to have a scheme and host specified, e.g./is acceptable.
For development, create a .env file (see .env.example) for convenience.
The backend takes configuration as command line parameters or environment variables:
--bind IP:PORTorBIND: the address and port to bind to.--github-client-id STRINGorGITHUB_CLIENT_ID: The GitHub client ID for this app (from GitHub app settings).--github-client-secretorGITHUB_CLIENT_SECRET: The GitHub client secret for this app (from GitHub app settings).
The backend should be proxied through the frontend URL at /api, e.g. a request
to http://frontend/api/health should be proxied to
http://backend/api/health.
Static mode doesn’t use a backend server, but the data file does need to be
updated periodically. scripts/generate-static.ts takes care of that:
--token-file PATH: A file containing only a GitHub personal access token (either classic of fine-grained) configured to allow read-only access to the repositories you care about. Defaults to.github-token.--output PATH: Where to save the data. Defaults todist/assets/github.json.
The frontend takes two optional environment variables:
VITE_CONTRIBUTIONS_URL: The URL to the GitHub format data file. Defaults toassets/github.json.VITE_LOCAL_CONTRIBUTIONS_URL: The URL to the local contributions data file. Defaults toassets/local.json.
Compact mode is configured just like static mode, except the frontend takes an additional, optional environment variable:
VITE_CLICK_URL: If this is set, clicking the graph in compact mode will navigate to this URL.
When creating a GitHub app or a personal access token, the following repository permissions are needed:
- Contents (read only)
- Issues (read only)
- Pull requests (read only)
This is a TypeScript and React app with a simple Rust backend built on Dropshot. Dropshot provides automatic OpenAPI support, which enables compile-time type checking of calls across the API boundary.
- Systemd socket activation. Dropshot takes a
SocketAddras configuration then binds aTcpListener. In order to use systemd socket activation, e.g. with systemd_socket, we need to pass Dropshot an already boundTcpListener, or some sort of generic that supportssystemd_socket::SocketAddr. This would require changes to Dropshot.
There are lots of similar projects out there. A few of them:
- https://github.com/tsaitoh/concal
- https://github.com/fledra/contribmap
- https://github.com/yaolifeng0629/contribution-map
- https://github.com/ammsa/Githeat
- https://github.com/sallar/github-contributions-chart
- https://github.com/james-stoup/heatwave
- https://github.com/SeiwonPark/react-contribution-calendar
- https://sourceforge.net/projects/repoheat/
Unless otherwise noted, this project is dual-licensed under the Apache 2 and MIT licenses. You may choose to use either.
Unless you explicitly state otherwise, any contribution you submit as defined in the Apache 2.0 license shall be dual licensed as above, without any additional terms or conditions.
