Feb 18, 2023
Automatically pull in release notes from your GitHub repo and display them on your site.
The GitHub API allows you to pull in content programmatically, such as release information. The following component fetches information for a release, and displays it in a custom layout, complete with GitHub Flavored Markdown for the main content. It is using the react-markdown component to convert a Markdown string into a React component. The result looks like this (here showing the React 18.2.0 release notes):
The component can be used as follows:
<ReleaseNotes repo="facebook/react" tagName="v18.2.0" />
Here is the code for the component:
import { useState, useEffect } from 'react'
import { format, parseISO } from 'date-fns'
import remarkGithub from 'remark-github@11.2.4'
export const ReleaseNotes = ({ repo, tagName }) => {
const [data, setData] = useState(undefined)
const [plugins, setPlugins] = useState([])
const [ReactMarkdownComp, setReactMarkdownComp] = useState(undefined)
useEffect(() => {
fetch(`https://api.github.com/repos/${repo}/releases`)
.then((r) => r.json())
.then((entries) => {
setData(entries.find(e => e.tag_name === tagName))
})
}, [repo, tagName])
useEffect(() => {
import('https://esm.sh/remark-gfm@3.0.1')
.then((mod) => mod.default)
.then(gfm => setPlugins(p => [...p, gfm]))
}, [])
useEffect(() => {
if (!plugins) {
return
}
import('https://esm.sh/react-markdown@8.0.5')
.then((mod) => mod.default)
.then(RM => {
setReactMarkdownComp(
<RM remarkPlugins={[
...plugins,
[remarkGithub, { repository: repo }]
]}>
{data.body}
</RM>)
})
}, [data, plugins])
if (!data) {
return <></>
}
return <div className="flex flex-col gap-4">
<div className="prose">
<h1>{data.name}</h1>
<div className="flex flex-row gap-1 items-center">
<div className="not-prose mr-2">
<img className="w-8 h-8 rounded-full" src={data.author.avatar_url} />
</div>
<a href={data.author.url}>{data.author?.login}</a>
released this on {format(parseISO(data.created_at), 'PPP')}
</div>
{ReactMarkdownComp}
</div>
</div>
}