Building MDX GitHub Embeds with Astro
Learn how to easily create MDX GitHub embeds using Astro in this step-by-step tutorial. Enhance your blog posts with dynamic GitHub content for a seamless and interactive reading experience. Here’s how to build an MDX GitHub embed with Astro!
Here’s an outline of the steps needed to build an MDX GitHub embed with Astro:
- Create a
<GhRepo />
Astro component - Use the component in an MDX file
- Cache data to sqlite with Prisma and sqlite
- Deploy to Netlify
1. Create a <GhRepo />
Astro component
Astro components are a great way to create reusable components and share them across your application. In this case, we’ll create a <GhRepo />
component that uses Ocotokit to pull repo datat from the GitHub API and display it in a card.
---import { GitHubIcon } from "./icons/index.astro";
interface Props { repo: string;}const { repo } = Astro.props;
async function getRepoData(repo: string) { const octokit = new Octokit({ auth: process.env.GH_TOKEN }); const repoSplit = repo.split("/"); const { data } = await octokit.rest.repos.get({ owner: repoSplit[0], repo: repoSplit[1], }); return data;}
const { full_name: fullName, description, stargazers_count: stargazersCount, html_url: url,} = await getRepo(repo);---
<a href={url} target="_blank" class="not-prose mb-4 block no-underline"> <section class="flex flex-col gap-2 rounded bg-gh-light p-2 sm:flex-row sm:gap-4 sm:p-4" > <GitHubIcon class="w-8 text-gh-dark sm:w-16" /> <div> <strong class="sm:text-lg">{fullName}</strong> <p class="sm:text-md text-sm leading-none text-gh-dark">{description}</p> <div class="text-gh-dark">🔭 {stargazersCount.toLocaleString()}</div> </div> </section></a>
It will look something like this:
The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno.
Note, I’m using TailwindCSS, and emoji, and an SVG icon component that I created. You can use whatever you want to style your component.
2. Use the component in an MDX file
To use the <GhRepo />
component in a MDX file, we will define it as a reusable component in the blog post layout’s Astro file.
---import { getCollection } from "astro:content";import type { CollectionEntry } from "astro:content";import { components } from "../../components/MdxComponents";import GhRepo from "./GhRepo.astro";
export async function getStaticPaths() { const posts = await getCollection("posts"); return posts.map((post) => { return { params: { slug: post.slug }, props: { post }, }; });}
interface Props { post: CollectionEntry<"posts">;}
const { post } = Astro.props;const { Content } = await post.render();---
<Content components={{ GhRepo }} />
Thanks to Stefan Imhoff (@kogakure) for the tip on twitter!
I highly recommend you check out Astro’s content collections guide to learn more about how to build type-safe markdown content.
Now, you can call the <GhRepo />
component in your markdown file, making sure to include the repo prop we defined.
---title: Building MDX GitHub Embeds with Astro---
It will look something like this:
<GhRepo repo="octokit/octokit.js" />
3. Cache data to sqlite with Prisma and sqlite
Next, we’ll want to create a Prisma model and service to cache the data from the GitHub API to sqlite. This will allow us to make fewer API calls and speed up our application.
model GhRepo { fullName String @unique description String? stargazersCount Int @default(0) url String @unique updatedAt DateTime @updatedAt @map("updated_at")}
You can learn more about how to use Prisma with sqlite in this guide.
Then, we’ll update the GhRepo
component logic to handle the API calls and caching.
async function addRepoToCache(repo: string) { const data = await getRepoData(repo); const dataToSave = { fullName: data.full_name, ...(data.description ? { description: data.description } : {}), stargazersCount: data.stargazers_count, url: data.html_url, }; return await prisma.ghRepo.upsert({ where: { fullName: data.full_name }, update: dataToSave, create: dataToSave, });}
async function getRepo(repo: string) { const cachedRepo = await prisma.ghRepo.findFirst({ where: { fullName: repo }, });
if ( !cachedRepo || cachedRepo.updatedAt < new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 7) ) { return await addRepoToCache(repo); } else { return cachedRepo; }}
const { fullName, description, stargazersCount, url } = await getRepo(repo);
A couple of things to notice here:
- Using an
upsert
allows us to update the repo if it already exists, or create it if it doesn’t. - A simple conditional check allows us to only call the GitHub API if the repo doesn’t exist in the database, or if it hasn’t been updated in the last week.
4. Deploy to Netlify
Finally, we can deploy the application to Netlify. It’s important to configure your Netlify configuration to run prisma’s migrate command before building the Astro app.
[build.environment] NPM_FLAGS = "--version" # prevent Netlify npm install
[build] command = 'npx pnpm i --store=node_modules/.pnpm-store && prisma migrate dev && npm run build' publish = 'dist'
That’s how you can build an MDX GitHub Embed with Astro, Prisma, and sqlite! We created a <GhRepo />
Astro component and styled it with TailwindCSS, pulled the data from the GitHu API using Octokit, cached it to local sqlite with Prisma, and deployed it to Netlify.
All the code can be found on the pull request from the live stream.
Thanks for reading! There are more Astro posts on the way, so make sure to subscribe to the newsletter to get notified when they’re published.
Sign-Up for New Posts
Stay in the loop and get the latest blog posts about development sent to your inbox.
Or use the