Building MDX GitHub Embeds with Astro hero

Building MDX GitHub Embeds with Astro

Development
01:36:15

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:

  1. Create a <GhRepo /> Astro component
  2. Use the component in an MDX file
  3. Cache data to sqlite with Prisma and sqlite
  4. 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.

GhRepo.astro
---
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:

octokit/octokit.js

The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno.

🔭 6,698

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.

PostLayout.astro
---
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.

building-mdx-github-embeds-with-astro.mdx
---
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.

schema.prisma
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.

GhRepo.astro
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:

  1. Using an upsert allows us to update the repo if it already exists, or create it if it doesn’t.
  2. 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.

netlify.toml
[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.

man sitting at desk in front of a landscape of rivers leading to a mountain range

Dev Workflow Intro

Your guide to creating a powerful and intuitive development workflow in the terminal.

The terminal is a powerful tool for developers, but it can be overwhelming to know where to start. This guide will help you create a powerful development environment in the terminal. Here are some of the things you'll learn.

  • Install packages and keep them up-to-date
  • Design a minimalist, distraction-free, user-interface
  • Use familiar keyboard shortcuts
  • Manage multiple projects with ease
  • Integrate with Git and GitHub
Get Started