本文へスキップ
作品一覧
公開中 · 誰でも使えます

GitLeaf

GitHubのコントリビューションを水彩画の植物にするサービスです。1年の1日1日が葉になり、その日の活動が多いほど葉の緑が濃くなります。プロフィールのREADMEに画像の1行を貼るだけで、絵は自動で最新になります。

1年のコントリビューションを描いた植物と、その葉のクローズアップ
種類
GitHub README向けの画像サービス
期間
2026年10月
運用環境
Cloudflare Workers + D1 + R2

概要

コントリビューショングラフは緑の四角が並んだ表です。眺めて楽しいものにしたくて、GitLeafは1年を植物として描きます。1日が小さな葉1枚で、活動が多いほど色が濃くなり、枝の先には1週間ぶんの大きな葉がつきます。まだ来ていない日は薄い輪郭だけで、絵の下には1年のコントリビューション数が入ります。

プロフィールのREADMEに置くための作りです。ユーザー名を入れた画像の1行を貼るだけで、登録もGitHub Actionsの設定も要りません。最初に画像が呼ばれたときにコントリビューションを読んで植物を描いて保存し、以降は同じURLのまま1日1回描き直します。READMEは書き換わらず、コミットも作られません。

葉は、AI画像ツールで作った水彩の葉8種類を、それぞれ5段階の濃さにしたものです。4本の茎に沿って並べ、1日に1枚ずつ当てはめるのがコードの仕事です。絵全体が1つのSVGファイルなので、スクリプトや外部への通信が使えないREADMEでも、ふつうの画像として表示されます。

主な機能

1日1枚の葉
葉の濃さはGitHubのコントリビューションレベルに従い、活動のない日は薄い輪郭、多い日は濃い緑になります。週ごとに、その週の平均を表す大きな葉もつきます。
1行で使える
ユーザー名を入れた画像の1行をREADMEに貼ります。アカウントは要らず、最初のリクエストで絵が表示されます。
毎日描き直し
同じURLで最新の活動が表示されるので、READMEを編集する必要はありません。年が変われば新しい植物になり、?year=で2008年まで好きな年を指定できます。
ほんの少しの風
?motion=breezeをつけると、枝がそれぞれのペースでゆっくり揺れます。CSSだけで動いていて、端末で動きを減らす設定にしていると止まります。
同じGitHubの活動から描いた、動かない絵と、ほんの少しの風で揺れる絵
同じアカウントの2024年・2025年・2026年。活動が多いほど葉が増え、色も濃くなる
しくみ。READMEがCloudflare Workerに画像を要求し、R2に保存したSVGを返す。毎日のCronがGitHubを読んで描き直し、D1が予定を管理する
READMEに貼る1行のコードと、それで表示される植物

技術構成

サービス
TypeScript · Cloudflare Workers(Cron Triggers)
保存
完成したSVGはR2、庭と更新時刻はD1
絵
素のJavaScriptで書いたSVG · 水彩の葉の画像8種類×5段階(sharp)· 風はCSSアニメーション
データ
GitHub GraphQL API(トークンはWorkerのシークレットに保管)
品質
実際のWorkersランタイムとD1・R2でのテスト(Miniflare)· GitHubとの実データ照合 · GitHub Actions

開発メモ

1回描いて、何度も返す

リクエストはR2に保存したSVGを返すだけで、ETagがあるので繰り返しも軽く済みます。GitHubを呼ぶのは最初の1回と毎日の描き直しのときで、READMEが表示されるたびではありません。

失敗しても植物は消さない

GitHubが失敗したり不完全なデータが返ったりしても前の絵を残し、再試行は1時間から最大1日まで間隔を広げます。D1のリースで、同時に来た2つのリクエストが同じ庭を二重に描くのも防ぎます。

描き直しは小さなバッチで

Cronは10分ごとに起き、更新時刻が来た庭を最大4つ処理します。庭ごとに1日1回、00:20 UTC以降です。仕事が小さいままで済み、利用者が増えたときの限界はREADMEに書いてあります。

GitHubの実データと照合

公開中の絵とGitHubの新しい応答を、日ごとの件数と濃さ、週ごとの葉、まだ来ていない日、合計まで照合するスクリプトがあります。20本のテストはGitHubに接続せずに動き、うるう年、年末の集中、障害時の動きまで確認します。

件数はコミットだけでなくGitHubのコントリビューションです。非公開の活動は、サービスのGitHubトークンから見える範囲しか反映されません。掲載の絵は自分のアカウントのものです。