Visual representation of git history with contributions stats, featuring text highlighted in green and blue for clarity.

I genuinely enjoy playing around with ideas that are completely useless on one hand, but also present very interesting problems to solve on the other hand. So recently I decided to play around with my GitHub user profile and the content it should show.

GitHub has pioneered a really open feature: Allowing users to completely customize their public profiles on their platform only with Markdown by utilizing a naming convention to create special repos (<username>/<username>). As one can imagine, this limits people to Markdown features1. However, developers love solving tricky challenges. And this has led to some really cool and creative inventions, like websites, which generate an SVG that you can embed in your profile Readme.

To name some examples I really enjoy: Astro Badges, Nuxters, GitHub Profile Stats and so many awesome more that this post could go on forever. Many users also handcraft their own creations, and so I decided to join them as well and share my learnings with the community here.

The idea

Since I was deep diving into Bento grids the other day, my vision of a fitting user profile was a grid of different stats put together in some aligning way.

I wanted some static stats, like my name with my profile picture blurred in the background and my Astro contributions. But to make it more challenging, I also wanted some dynamic elements: My GitHub contribution heatmap being eaten by a 2D snake (which is from a project I discovered recently) and a widget of a recent song I played on Spotify2.

The limitation

When I wrote "limited to Markdown", I was lying a little bit. You can also put HTML elements into your Markdown files and they render fine. For security reasons however, GitHub strictly refuses to render stuff like <iframe>s, which to my knowledge is necessary if you want some dynamically embedded stuff (without relying on GitHub actions).

Another potential solution I played around with were generating images of the dynamically generated content on a schedule in a script called by a GitHub action. But then I would not be able to have continuous animations on the profile.

One info worth mentioning is that GitHub has also built in security measures to not execute fetches from the Markdown. Even when you embed an SVG image, which uses foreignObject, fetches are still blocked. To work around this, we base64-encode the prefetched images.

There were some other ideas along my little journey, but a very helpful StackOverflow entry demonstrated a workaround to get more HTML possibilities out of GFM. This hint together with base64-encoded data URLs allowed me to open Pandora's box 🥳

The implementation

The final setup works like this:

  1. 1.

    Every 30 minutes, a GitHub action triggers, which executes a build script.

  2. 2.

    This script fetches two APIs for the two dynamic elements: Spotify and snk/svg-only3

  3. 3.

    It then base64-encodes the resulting SVG files and creates data URLs.

  4. 4.

    Those huge URLs can then be included in a bento grid HTML template with prefilled styles and desired layout.

  5. 5.

    This generated HTML is then wrapped in a foreignObject tag in an SVG, which is committed to the repository.

  6. 6.

    The Readme then just has to include the SVG with Markdown image syntax and since all data is stored within the SVG (no external fetches anymore), it renders on my profile.

It's not beautiful internally, but its presence shines. Feel free to check out the final result out on my GitHub.