Skip to content
HiDeoo

List recent GitHub releases in Starlight using the Astro Content Layer API

Published on - Reading time

Announced in June 2024, the Astro Content Layer API is a new approach to working with local and remote content sources in Astro. Built upon the Content Collections API, the Content Layer API is designed to be more flexible and powerful and is available behind an experimental flag starting with Astro 4.14.

At the time of writing, Starlight does not yet support the Content Layer API for documentation pages but you can still use it in a Starlight project.

This guide will show you how to use this new experimental feature to create a page in your Starlight documentation website listing the recent GitHub releases for a specific repository. To do so, we will use the Astro feed loader to fetch the latest releases from an Atom feed and display them on a custom page.

Prerequisites

You will need to have an existing Starlight website using Astro 4.14 or later.

Install the feed loader

Start by installing the @ascorbic/feed-loader package:

npm install @ascorbic/feed-loader

Enable the Content Layer API

To get started with the Content Layer API, you will need to enable the experimental flag in your astro.config.mjs file:

astro.config.mjs
import { defineConfig } from 'astro/config'
import starlight from '@astrojs/starlight'
export default defineConfig({
experimental: {
contentLayer: true,
},
integrations: [starlight({ title: 'My Docs' })],
})

Load recent GitHub releases

To load content with the Content Layer API, the Astro feed loader can be used when defining a collection in the src/content/config.ts file.

The loader takes a URL as input which will be fetched and parsed as an Atom feed. GitHub provides an Atom feed for the releases of a repository using the following URL format: https://github.com/OWNER/REPO/releases.atom.

The following example defines a new collection named releases that fetches the latest releases of the Starlight repository:

src/content/config.ts
import { defineCollection } from 'astro:content'
import { docsSchema } from '@astrojs/starlight/schema'
import { feedLoader } from '@ascorbic/feed-loader'
export const collections = {
docs: defineCollection({ schema: docsSchema() }),
releases: defineCollection({
loader: feedLoader({
url: 'https://github.com/withastro/starlight/releases.atom',
}),
}),
}

List recent releases

To list the recent releases, Astro’s file-based routing can be used to create a new page in the src/pages/ directory.

The new page will use the <StarlightPage /> component to render the content using the default Starlight layout and the getCollection() function to query the releases collection created earlier.

src/pages/releases.astro
---
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'
import { getCollection } from 'astro:content'
// Query the releases collection to get the recent releases.
const releases = await getCollection('releases')
---
<StarlightPage frontmatter={{ title: 'Recent Releases' }}>
{
releases.map((release) => {
// Loop over the releases to display their titles.
return <h2>{release.data.title}</h2>
})
}
</StarlightPage>

The above example will render the following content:

Recent Releases

@astrojs/starlight@0.27.1

@astrojs/starlight-markdoc@0.1.0

@astrojs/starlight@0.27.0

@astrojs/starlight@0.26.4

@astrojs/starlight@0.26.3

@astrojs/starlight@0.26.2

@astrojs/starlight@0.26.1

@astrojs/starlight@0.26.0

@astrojs/starlight@0.25.5

@astrojs/starlight@0.25.4

Display release details

Instead of only listing the release titles, we can render a custom Astro component to display more information about each release.

src/components/Release.astro
---
import { render, type CollectionEntry } from 'astro:content'
interface Props {
release: CollectionEntry<'releases'>
}
// Render the release content.
const { release } = Astro.props
const { Content } = await render(release)
---
<article>
<h2 id={release.id}>{release.data.title}</h2>
<Content />
</article>

The above example will render the following content:

@astrojs/starlight@0.25.5

Patch Changes

Fill in the table of contents

When using the <StarlightPage /> component, the table of contents will not be automatically filled with the content of the page. To do so, the headings property can be used to specify an array of headings to include in the table of contents.

src/pages/releases.astro
---
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'
import { getCollection } from 'astro:content'
import Release from '../components/Release.astro'
const releases = await getCollection('releases')
// Loop over the releases to create the table of contents.
const headings = releases.map((release) => ({
slug: release.id,
text: release.data.title,
depth: 2,
}))
---
<StarlightPage frontmatter={{ title: 'Recent Releases' }} {headings}>
{releases.map((release) => <Release {release} />)}
</StarlightPage>

Up to you to customize the content of the release details component to display more information, e.g., the release date, the author, etc.

You can find the complete source code of this guide in this StackBlitz example.