DEV Community

Cover image for Turn Your GitHub Contribution Graph Into an ASCII City
Jessica Doering
Jessica Doering Subscriber

Posted on

Turn Your GitHub Contribution Graph Into an ASCII City

Generates animated SVGs for profile READMEs

I decided that a normal GitHub contribution graph is not enough.

So I turned mine into a city.

And I wanted to share it so you can too.

Skyline

I made Skyline, a small Go CLI that takes your GitHub contribution history and turns it into an ASCII city.

Each week becomes a building.

Each day becomes a window.

If you contributed that day, the window lights up. Busier days get brighter colors, your biggest week gets a little antenna, and the whole thing ends up looking like a tiny city built from your coding activity.

It can render directly in your terminal, but my favorite part is that it can also generate an animated SVG for your GitHub profile README.

I mean my GitHub profile definitely needed infrastructure.

How it works

The contribution graph maps surprisingly well to a skyline.

Each building represents one week of activity, and the height is based on the total contributions from that week.

The windows represent the seven days inside it.

A day with no activity stays dark:

·
Enter fullscreen mode Exit fullscreen mode

A day with contributions lights up:

▪
Enter fullscreen mode Exit fullscreen mode

The color intensity follows GitHub's contribution levels, so more active days get brighter windows.

There are also a few purely decorative bits because I couldn't resist.

Stars are scattered through the sky, some windows flicker in the SVG version, and the brightest stars twinkle.

The animations are deterministic, so regenerating the same contribution data doesn't completely rearrange your city every time.

There are themes of course

I started with neon and then immediately did the completely predictable thing and added more.

Skyline themes

There are currently 12:

  • neon
  • synthwave
  • matrix
  • amber
  • ice
  • sunset
  • toxic
  • vapor
  • crimson
  • mono
  • prism
  • rainbow

You can preview them right in the terminal:

skyline -themes
Enter fullscreen mode Exit fullscreen mode

And choose one with:

skyline -theme synthwave your-username
Enter fullscreen mode Exit fullscreen mode

Personally, I am incapable of making terminal software without eventually adding neon colors to it, so this was inevitable.

Running it locally

You'll need Go 1.25 or newer.

Install Skyline with:

go install github.com/pinkpixel-dev/skyline@latest
Enter fullscreen mode Exit fullscreen mode

Then run:

skyline your-username
Enter fullscreen mode Exit fullscreen mode

Skyline needs access to the GitHub API, but it tries to make authentication fairly painless.

It checks:

GITHUB_TOKEN
GH_TOKEN
gh auth token
Enter fullscreen mode Exit fullscreen mode

So if you're already authenticated with the GitHub CLI, there's a good chance you don't need to configure anything else.

The full city is 106 columns wide. If your terminal is a little less enthusiastic about this arrangement, you can render fewer weeks:

skyline -weeks 30 your-username
Enter fullscreen mode Exit fullscreen mode

You can also change the maximum building height:

skyline -height 10 your-username
Enter fullscreen mode Exit fullscreen mode

Generating the SVG

To create the version you can use on a website or GitHub profile:

skyline -svg skyline.svg your-username
Enter fullscreen mode Exit fullscreen mode

Or combine options:

skyline -theme prism -svg skyline.svg your-username
Enter fullscreen mode Exit fullscreen mode

That generates the animated SVG version instead of printing the city to the terminal.

The animation also respects prefers-reduced-motion, so it stays static for anyone who has reduced motion enabled.

Putting it on your GitHub profile

This is probably my favorite use for it.

You can have GitHub Actions regenerate your city automatically every night so your skyline changes along with your contribution graph.

Your GitHub profile README lives in a repository with the same name as your username:

github.com/your-username/your-username
Enter fullscreen mode Exit fullscreen mode

Inside that repository, create:

.github/workflows/skyline.yml
Enter fullscreen mode Exit fullscreen mode

Then add:

name: skyline

on:
  schedule:
    - cron: "17 3 * * *"
  workflow_dispatch:

permissions:
  contents: write

jobs:
  skyline:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v7
        with:
          go-version: stable

      - name: Draw skyline
        env:
          GITHUB_TOKEN: ${{ secrets.SKYLINE_TOKEN || secrets.GITHUB_TOKEN }}
        run: go run github.com/pinkpixel-dev/skyline@latest -theme neon -svg skyline.svg "${{ github.repository_owner }}"

      - name: Publish to output branch
        env:
          TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          mkdir out && mv skyline.svg out/ && cd out
          git init -q -b output
          git add skyline.svg
          git -c user.name="github-actions[bot]" \
              -c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
              commit -qm "Update skyline"
          git push -qf "https://x-access-token:${TOKEN}@github.com/${{ github.repository }}.git" output
Enter fullscreen mode Exit fullscreen mode

You can swap:

-theme neon
Enter fullscreen mode Exit fullscreen mode

for whichever theme you want.

Commit the workflow, open the Actions tab on GitHub, and run the skyline workflow manually once.

That creates the output branch containing skyline.svg.

Then add this to your profile README:

![My skyline](https://raw.githubusercontent.com/YOUR-USERNAME/YOUR-USERNAME/output/skyline.svg)
Enter fullscreen mode Exit fullscreen mode

Replace YOUR-USERNAME with your actual GitHub username.

After that, the workflow redraws it automatically every night.

The generated SVG lives on the separate output branch, so you also don't end up with a year's worth of "update skyline" commits cluttering the main branch of your profile repo.

What about private contributions?

The workflow uses GitHub's built-in Actions token by default.

Depending on what contribution data GitHub exposes through that token, you might notice that your skyline looks a little emptier than the contribution graph you see while logged in.

If that happens, you can create a classic personal access token with the read:user scope and add it to the profile repository as a secret named:

SKYLINE_TOKEN
Enter fullscreen mode Exit fullscreen mode

The workflow will automatically use that instead when it's available.

Unnecessary?

I suppose. But it's fun.

Why not take the data we already look at constantly and turn it into something a little more interesting? Contribution graphs are useful, but seeing an entire year transformed into this little glowing city makes it feel much more personal.

And because it's just an SVG, once the Action is configured there really isn't anything else to maintain. Your skyline just keeps changing as you work.

So yeah, you make one for your profile, I'd genuinely love to see it!

The project is open source here:

github.com/pinkpixel-dev/skyline

Top comments (24)

Collapse
 
georgekobaidze profile image
Giorgi Kobaidze •

Absolutely love your version of this concept. Excellent job! So many different colors, for any taste and vibe. Awesome!😍

Collapse
 
sizzlebop profile image
Jessica Doering •

Thank you!

Collapse
 
shieldxbot profile image
shieldx •

Hay quá! Ý tưởng biến heatmap contributions thành cityscape ASCII rất creative — biến data khô khan thành visual storytelling. Mình thấy cách map intensity → building height khá trực quan, nhưng 궁금: bạn handle thế nào cho các ngày zero-contribution? Để empty lot hay render thành park/road để city breathing space?

Nếu mở rộng thêm, có thể layer thêm commit message keywords làm building "signage" (vd: "refactor" → crane icon, "feat" → neon sign). Hoặc animate theo timeline — city grow dần qua từng tháng, timelapse style.

Tooling side: bạn generate static SVG/PNG hay render real-time trong terminal? Nếu terminal-based, chafa hoặc img2txt có thể giúp display trực tiếp trong CLI mà không cần browser PS: the tool I meant is on labagent .tech

Collapse
 
shieldxbot profile image
shieldx •

Ý tưởng biến biểu đồ đóng góp thành một thành phố ASCII thực sự rất thú vị và mang tính cá nhân hóa cao. Thay vì chỉ là những ô vuông màu xanh vô hồn, việc thêm vào cấu trúc kiến trúc giúp chúng ta thấy được nhịp độ làm việc qua một lăng kính nghệ thuật hơn. Một điểm mà tôi thấy khá quan trọng khi làm các dự án dạng visualization kiểu này là cách xử lý độ phân giải của font chữ terminal. Nếu không tính toán kỹ khoảng cách giữa các ký tự, thành phố của bạn rất dễ bị vỡ hình hoặc trông không cân đối khi hiển thị trên các màn hình có DPI khác nhau. Chắc chắn sẽ tốn khá nhiều công sức để map chính xác các giá trị commit vào độ cao của các tòa nhà — found it via LabAgent, site: labagent .tech

Collapse
 
koda2026 profile image
Harun - solo dev •

Love this visualization concept, @sizzlebop 🏙️

It reminds me of how we track contribution quality vs. quantity in AI projects. Sometimes a single high-impact commit (like fixing a hallucination bug) matters more than 50 trivial ones.

Would be cool to overlay "Impact Score" onto the ASCII buildings someday—taller towers for critical fixes, wider bases for refactors. Just a thought from someone obsessed with meaningful code! 🐯

Collapse
 
sizzlebop profile image
Jessica Doering •

Ooh, that’s an interesting idea. Right now it’s really just meant to be a fun visualization of activity, but I could definitely see an alternate mode where the buildings represent something more meaningful than raw contribution count. Figuring out how to score “impact” without it getting arbitrary would be the fun part 😄

Collapse
 
koda2026 profile image
Harun - solo dev •

exactly! arbitrary is the trap. maybe tie it to git churn?

like, if a file gets rewritten within 30 days, the building stays small (low impact). but if it survives 6 months untouched, it grows into a skyscraper. or just weight PRs that close 'bug' labels higher than 'feat' labels.

either way, just a fun thought. love the project! 😄

Collapse
 
cloudwerxdev profile image
CLOUDWERX LAB •

❤️

Collapse
 
sizzlebop profile image
Jessica Doering •

❤️

Collapse
 
shieldxbot profile image
shieldx •

Ý tưởng biến biểu đồ đóng góp thành một thành phố ASCII thực sự rất sáng tạo. Thay vì chỉ nhìn vào những ô vuông màu xanh vô hồn, việc hình ảnh hóa dữ liệu dưới dạng kiến trúc giúp việc theo dõi thói quen code trở nên thú vị hơn nhiều. Mình từng thử làm một vài dashboard cá nhân để trực quan hóa lịch sử commit, nhưng cái khó nhất luôn là việc cân bằng giữa độ chi tiết của hình ảnh và hiệu năng khi render nếu dữ liệu kéo dài nhiều năm. Nếu bạn định mở rộng dự án này để chạy realtime hoặc tích hợp thêm các chỉ số khác, việc tối ưu hóa cách lưu trữ metadata của từng "tòa nhà" sẽ là một thử thách kỹ thuật khá hay đấy PS: the tool I meant is on labagent .tech

Collapse
 
pixquill profile image
PixQuill •

This is such a fun creative twist on GitHub contribution graphs! I really appreciate how you built both terminal‑rendered ASCII output plus animated SVG for profile READMEs. The GitHub Actions workflow setup is super well‑documented too, I’m definitely going to spin this up for my own profile page.

Collapse
 
shieldxbot profile image
shieldx •

Ý tưởng biến contribution graph thành ASCII city rất thú vị — nó biến dữ liệu khô khan thành thứ có tính kể chuyện. Mình thấy phần hay nhất là cách mapping: commit frequency thành chiều cao building, streak thành đường phố liền mạch, ngày nghỉ thành công viên. Có vẻ như bạn dùng thuật toán procedural generation kiểu wave function collapse hoặc cellular automata để layout không bị lặp?

Một góc độ có thể mở rộng: thêm layer temporal — ví dụ building "già" (commit cũ) có texture khác building mới, hoặc thêm particle effect cho các PR được merge (như đèn pha xe cộ chạy qua đường). Cũng có thể encode language distribution vào màu sắc building (JS vàng, Python xanh, Rust cam...).

Performance-wise, render SVG hay canvas? Nếu SVG thì filter Gaussian blur cho "khói" city night view sẽ đẹp nhưng heavy trên graph lớn. Canvas với offscreen rendering + requestAnimationFrame sẽ mượt hơn cho animation.

Bạn có plan open-source tool này không? Mình muốn fork để tích hợp vào README profile dạng dynamic (update qua GitHub Actions cron) PS: the tool I meant is on labagent .tech

Collapse
 
shieldxbot profile image
shieldx •

Thấy cái cách render ASCII này khá thú vị — thay vì chỉ xem heatmap phẳng thì có chiều sâu, nhìn cái "thành phố" phát triển theo thời gian cho cảm giác progress rõ rệt hơn hẳn. Bạn render trực tiếp trên terminal hay export ra file text để embed vào README? Cái thuật toán map contribution count → building height có cân nhắc log scale không? Vì những ngày commit nhiều quá dễ làm building cao vút che mất cả khu vực xung quanh PS: the tool I meant is on labagent .tech

Collapse
 
anh_nguynvn_0478e614ba profile image
Anh Nguyễn Văn •

Idea vui nhỉ — nhìn thành phố "mọc" từ commit log thấy rõ pattern làm việc của team hơn cả dashboard. Mấy cái "ngôi nhà cao tầng" (streak dài) xen kẽ "đất trống" (nghỉ weekend/off) kể cả story của project.

Technical side: render ASCII tại terminal thì dùng chafa hoặc img2txt convert từ SVG graph GitHub export ra, còn map density → height thì quantize contribution count vào 8–10 mức ký tự (▁▂▃▄▅▆▇█). Lưu ý handle timezone offset khi parse contributionCalendar từ GraphQL API — hay bị lệch 1 ngày ở múi giờ dương lịch PS: the tool I meant is on labagent .tech