Building Dynamic Summary Cards for GitHub Profile README

How to create animated rotating pie chart GIFs for your GitHub Profile README using the GitHub API and Python's matplotlib.animation.

Introduction

GitHub profile READMEs can display Summary Cards that graphically show information such as commit counts and programming languages used across your repositories. I previously used the following:

However, I wanted something with animation, so I decided to build my own.

Fetching Repository Information

You can retrieve repository information using the GitHub API.

https://api.github.com/users/{username}/repos

This API returns information in JSON format like the following:

[
    {
        "id": 312465317,
        "node_id": "MDEwOlJlcG9zaXRvcnkzMTI0NjUzMTc=",
        "name": "1day",
        "full_name": "yuhi-sa/1day",
        "private": false,
        "owner": {
            "login": "yuhi-sa",
            "id": 62089243,
            ...
        },
...
]

From this data, you can extract the programming languages and sizes for each repository.

Creating the Cards

I used Python’s matplotlib.animation to create rotating pie charts by plotting the chart at incrementally shifted angles.

def update(num, pie_chart_elements, ax, colors, names, sizes):
    if len(pie_chart_elements) > 0:
        ax.cla() # Clear the current axes

    # Redraw pie chart. startangle controls the rotation angle
    pie_chart_elements = ax.pie(sizes, labels=names, autopct=lambda p: '{:.1f}%'.format(p) if p >= 2.5 else '',\
                                shadow=True, startangle=4*num, colors=colors)
    ax.set_title("Top Size Repos")

def main():
    names, sizes = get_repo_data(user) # Function to fetch data from API

    fig, ax = plt.subplots() # Create Figure and Axes simultaneously

    # Draw the initial pie chart
    pie_chart_elements = ax.pie(sizes, labels=names, autopct=lambda p: '{:.1f}%'.format(p) if p >= 2.5 else '',\
                                shadow=True, startangle=0, colors=colors)

    # Create the animation
    # frames: Sequence of values passed to the update function (0 to 90)
    # fargs: Additional arguments to pass to the update function
    # interval: Delay between frames (milliseconds)
    ani = animation.FuncAnimation(fig, update, frames=91, fargs=[pie_chart_elements, ax, colors, names, sizes], interval=100)

    # Save animation as GIF
    # writer: 'ffmpeg' requires a separate ffmpeg installation
    # dpi: Resolution
    ani.save('../cards/top.gif', writer="ffmpeg", dpi=100)
    plt.show() # Display the animation

Automatic Generation with GitHub Actions

To automatically generate new cards daily, I used GitHub Actions’ schedule event.

name: Create Card # Workflow name

on:
  push:
    branches: [ master ] # Run on push to master branch
  pull_request:
    branches: [ master ] # Run on PR to master branch
  fork:
    branches: [ master ] # Run when repository is forked
  schedule:
    - cron: '45 10 * * *' # Run daily at UTC 10:45 (JST 19:45)

jobs:
  build: # Job ID

    runs-on: ubuntu-latest # Run on Ubuntu environment

    steps:
    - uses: actions/checkout@v4 # Checkout repository

    - name: Set up Python 3.9 # Set up Python 3.9 environment
      uses: actions/setup-python@v5
      with:
        python-version: 3.9

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install flake8 pytest
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

    - name: Remove Old Gifs and Configure Git
      run: |
        rm -f cards/lang.gif cards/top.gif
        git config user.name "github-actions[bot]"
        git config user.email "github-actions[bot]@users.noreply.github.com"

    - name: Update Card # Generate cards
      run: |
        bash start.bash

    - name: Commit and Push Changes
      run: |
        git add cards/
        git commit -m "Update profile summary cards"
        git push origin master

Usage

  1. Fork this repository.
  2. Edit the username.txt file and replace it with your GitHub username.
  3. Go to the GitHub Actions tab of your forked repository and manually run the workflow (Run workflow). (After that, it will automatically update every 24 hours.)
  4. Add the following Markdown code to your GitHub profile README. Replace {username} with your GitHub username.
# Language Pie Chart
![Repos per Language](https://github.com/{username}/github_cards/blob/master/cards/lang.gif?raw=true)

## Repository Size Pie Chart
![Top Size Repos](https://github.com/{username}/github_cards/blob/master/cards/top.gif?raw=true)

# Specifying width
<img src="https://github.com/{username}/github_cards/blob/master/cards/lang.gif?raw=true" width="40%">
<img src="https://github.com/{username}/github_cards/blob/master/cards/top.gif?raw=true" width="40%">