Rehype plugin that turns GitHub links into badges

This post explains how to create a Rehype plugin to transform Markdown links that link to GitHub users or organisations into beautiful badges.

The inspiration for the design was taken from none other than @antfu.me himself, as they have those badges all over the place on their website (as time of writing).

If you are looking for the equivalent Sätteri plugin (for Astro 7+), check out this post.

This is the whole code behind the Rehype plugin:

// src/lib/rehype-github-badge-links.ts
import { h } from "hastscript";
import { visit } from "unist-util-visit";

export default function rehypeGitHubBadgeLinks() {
return (tree) => {
visit(tree, "element", (node) => {
if (
node.tagName === "a" &&
typeof node.properties?.href === "string" &&
node.properties.href.startsWith("https://github.com/")
) {
const match = node.properties.href.match(
/^https:\/\/github\.com\/([\w-]+)\/?$/
);
if (match) {
const username = match[1];
// Add GitHub badge class
node.properties.className = (node.properties.className || []).concat(
"gh-badge"
);

// Build avatar image
const avatarImg = h("img", {
src: `https://github.com/${username}.png`,
alt: username,
});
// Prepend avatar image to original children
node.children.unshift(avatarImg);
}
}
});
};
}

Basically all this plugin does, is walking through the HTML, looking for links which reference to any GitHub profile. If it finds one, it adds an tag before the text content with the profile picture of the GitHub user or organisation. This is possible very consistently thanks to GitHub's feature of making the picture available as a resource behind the profile link appended with .png. Read more about that feature in this awesome article on dev.to.

With a little bit of additional styling it looks really cute in my opinion.1

.gh-badge {
display: inline-flex;
align-items: center;
background-color: var(--sl-color-accent-low);
border-radius: 9999px;
padding: 0em 0.5em 0 0.3em;
font-size: 0.9em;
text-decoration: none;
color: inherit;
font-weight: 500;
transition: background-color 0.2s ease;
transform: translateY(0.29rem);
border: 1px solid var(--sl-color-accent);
}

.gh-badge:hover {
background-color: var(--sl-color-accent);
}

.gh-badge img {
border-radius: 9999px;
width: 1.3em;
height: 1.3em;
}

Now to put everything together, let's say for example in an Astro site, you just need to add the Rehype plugin to the configuration like this:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import rehypeGitHubBadgeLinks from "./src/lib/rehype-github-badge-links";

export default defineConfig({
markdown: {
rehypePlugins: [rehypeGitHubBadgeLinks]
}
})

Read more about the injection of Rehype plugins in Astro in their configuration reference.

Do not forget to add the CSS in a similar way depending on your framework - in Starlight you can configure custom global CSS styles following these instructions - and you can admire your own badge links too. Feel free to share this post with anyone you want to persuade to use these features too.

Please note that since I made the badges for a Starlight site, I use its CSS variables. You can play around with colours as you like.