Mirror of
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: write new blog about gh badge links (rehype plugin)

+165
starlight/public/blog/rehype-github-badge-links.png

This is a binary file and will not be displayed.

+8
starlight/src/components/BadgeLink.astro
··· 1 + --- 2 + const { href, src, text, className = "gh-badge" } = Astro.props; 3 + --- 4 + 5 + <a href={href} class={className}> 6 + <img src={src} alt={text} /> 7 + {text} 8 + </a>
+9
starlight/src/components/StarlightBadgeLink.astro
··· 1 + --- 2 + import BadgeLink from "./BadgeLink.astro"; 3 + --- 4 + 5 + <BadgeLink 6 + href="https://github.com/withastro/starlight" 7 + src="/starlight.png" 8 + text="Starlight" 9 + />
+148
starlight/src/content/docs/blog/rehype-github-badge-links.mdx
··· 1 + --- 2 + title: How to create a Rehype plugin that turns GitHub links into beautiful badges 3 + description: TOD 4 + date: 2025-07-12 5 + tags: 6 + - Plugins 7 + authors: 8 + - trueberryless 9 + excerpt: TODO 10 + cover: 11 + alt: A beautiful cover image with the text "Badge Links" 12 + image: ../../../../public/blog/rehype-github-badge-links.png 13 + tableOfContents: false 14 + --- 15 + 16 + import StarlightBadgeLink from "../../../components/StarlightBadgeLink.astro"; 17 + 18 + Recently, I added a very little neat feature to this blog, which you might have noticed as a regular reader. It's nothing huge, but gives every blog this little lovely touch I, which I have longed for a long time. I am ~talking~ writing about all those green badges with profile pictures you can see in this blog as well. 19 + 20 + The inspiration to create them was taken from none other than [Antfu](https://github.com/antfu) himself, as he has those badges all over the place on his website (as time of writing). 21 + 22 + Initially I thought they would require some long and tedious programming session to accomplish the same visual beauty. However, after some Vibe Coding - as [Andrej Karpathy coined the term](https://x.com/karpathy/status/1886192184808149383) - I quickly realized that those badges were just a small [rehype](https://github.com/rehypejs) plugin away from existence. 23 + 24 + This is the whole code behind the rehype plugin: 25 + 26 + ```ts 27 + // src/lib/rehype-github-badge-links.ts 28 + import { h } from "hastscript"; 29 + import { visit } from "unist-util-visit"; 30 + 31 + export default function rehypeGitHubBadgeLinks() { 32 + return (tree) => { 33 + visit(tree, "element", (node) => { 34 + if ( 35 + node.tagName === "a" && 36 + typeof node.properties?.href === "string" && 37 + node.properties.href.startsWith("https://github.com/") 38 + ) { 39 + const match = node.properties.href.match( 40 + /^https:\/\/github\.com\/([\w-]+)\/?$/ 41 + ); 42 + if (match) { 43 + const username = match[1]; 44 + 45 + // Add GitHub badge class 46 + node.properties.className = (node.properties.className || []).concat( 47 + "gh-badge" 48 + ); 49 + 50 + // Build avatar image 51 + const avatarImg = h("img", { 52 + src: `https://github.com/${username}.png`, 53 + alt: username, 54 + width: 16, 55 + height: 16, 56 + style: 57 + "border-radius:9999px;vertical-align:middle;margin-right:0.4em;", 58 + }); 59 + 60 + // Prepend avatar image to original children 61 + node.children.unshift(avatarImg); 62 + } 63 + } 64 + }); 65 + }; 66 + } 67 + ``` 68 + 69 + 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 `<img>` 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`](https://dev.to/10xlearner/how-to-get-the-profile-picture-of-a-github-account-1d82). 70 + 71 + With a little bit of additional styling it looks really cute in my opinion. Please note that since this is a <StarlightBadgeLink /> page, I use available CSS variables, like in line four: 72 + 73 + ```css "var(--sl-color-accent-low)" "var(--sl-color-accent)" 74 + // src/styles/custom.css 75 + .gh-badge { 76 + display: inline-flex; 77 + align-items: center; 78 + background-color: var(--sl-color-accent-low); 79 + border-radius: 9999px; 80 + padding: 0em 0.5em 0 0.3em; 81 + font-size: 0.9em; 82 + text-decoration: none; 83 + color: inherit; 84 + font-weight: 500; 85 + transition: background-color 0.2s ease; 86 + transform: translateY(0.29rem); 87 + border: 1px solid var(--sl-color-accent); 88 + } 89 + 90 + .gh-badge:hover { 91 + background-color: var(--sl-color-accent); 92 + } 93 + 94 + .gh-badge img { 95 + border-radius: 9999px; 96 + width: 1.3em; 97 + height: 1.3em; 98 + } 99 + ``` 100 + 101 + 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: 102 + 103 + ```ts ins={6-8} 104 + // astro.config.mjs 105 + import { defineConfig } from 'astro/config'; 106 + import rehypeGitHubBadgeLinks from "./src/lib/rehype-github-badge-links"; 107 + 108 + export default defineConfig({ 109 + markdown: { 110 + rehypePlugins: [rehypeGitHubBadgeLinks] 111 + } 112 + }) 113 + ``` 114 + 115 + Read more about the injection of rehype plugins in Astro in [their configuration reference](https://docs.astro.build/en/reference/configuration-reference/#markdownrehypeplugins). 116 + 117 + 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](https://docs.astro.build/en/guides/styling/#scoped-styles) - 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. 118 + 119 + <details> 120 + <summary>✨ Bones point</summary> 121 + 122 + If you want to use such a badge for other links too, I recommend that you craft yourself a little Astro component like this one: 123 + 124 + ```astro 125 + --- 126 + // src/components/BadgeLink.astro 127 + const { href, src, text, className = "gh-badge" } = Astro.props; 128 + --- 129 + 130 + <a href={href} class={className}> 131 + <img src={src} alt={text} /> 132 + {text} 133 + </a> 134 + ``` 135 + 136 + Just make sure that the CSS is globally (or [scope](https://docs.astro.build/en/guides/styling/#scoped-styles) it in the component above) and it's ready to be used: 137 + 138 + ```mdx 139 + import BadgeLink from "../components/BadgeLink.astro"; 140 + 141 + <BadgeLink 142 + href="https://github.com/withastro/starlight" 143 + src="/starlight.png" 144 + text="Starlight" 145 + /> 146 + ``` 147 + 148 + </details>