Skip to content

Creating Guides & How Starlight Works

What is Starlight?

Starlight is a documentation site generator built on top of Astro, a popular modern web framework, by the Astro team itself. Starlight is designed to be fast, flexible, and easy to use, making it a great choice for creating documentation sites. It supports Markdown and MDX, allowing you to write content in a familiar format while also enabling extensive access to the entire modern web ecosystem if needed.

For RIOT Starlight is meant to exclusively host guides while the API documentation is generated by Doxygen and hosted on the RIOT API documentation site. Where Doxygen has a very automated approach to generating documentation, Starlight is meant to be more flexible and allow for a more human touch that is needed for tutorials and guides, which means that we both have the control over the content and layout but at the same time have to put more active effort into the UX of the documentation itself. At the same time writing guides in Markdown allows us to keep the guides readable in the repository itself, which is a big plus.

How to run the site locally

To run the site locally, you need to have Node.js installed. It is highly recommended to use a version manager such as NVM to manage your Node.js versions.

Please make sure to use a fairly recent version of Node.js, some distributions (such as Ubuntu) ship with a very old version of Node.js that is not compatible with Starlight. Generally, the latest LTS version should work fine (As of writing v22), as specified in the Astro documentation.

Once installed you should be able to install the dependencies and run the site locally with the following command, making sure to be within the root of the repository:

Running the site locally (within the root of the repository)
make doc-starlight

This will start a local development server and open the site in your default web browser. The resulting output should look like this:

Output of running the site locally
(3.12.8) [user@computer RIOT]$ make doc-starlight
Installing starlight...
Starlight installed successfully.
Starting starlight live server...
> guide@0.0.1 dev
> astro dev
13:32:10 [types] Generated 0ms
13:32:10 [content] Syncing content
13:32:10 [content] Synced content
astro v5.6.1 ready in 1490 ms
Local http://localhost:4321/
Network use --host to expose
13:32:10 watching for file changes...

You can then browse the site at the URL shown in the output, which is usually http://localhost:4321/.

One big advantage of Starlight is that it supports hot reloading, which means that any changes you make to the content will be reflected in the browser immediately without needing to refresh the page. This makes it easy to see how your changes affect the site in real-time.

You can also use the make build command within the doc/starlight folder to build the site for production. This will create a static version of the site in the dist directory, which can be deployed to any static file hosting service.

Building the site for production
cd doc/starlight && make build

Folder Structure

Generally, there are two folders that are important for the guides:

  • doc/guides/: This folder contains the actual guides. Each guide is a Markdown file with a specific structure that Starlight uses to generate the navigation and other metadata for the guide.
  • doc/starlight/: This folder contains the Starlight configuration files. The most important file is astro.config.mjs, which contains the configuration for the site, including the navigation structure and other settings.

We will go into more detail about how to create a new guide in the next section, but for now, it is important to understand that the guides are located in the doc/guides/ folder and the configuration files are located in the doc/starlight/ folder.

How to create a new guide

Now that we understand how to run the site locally, let’s look at how to create a new guide. The first step is to create a Markdown file within doc/guides/ with the following structure:

doc/guides/test/hello_world.md
---
title: My New Guide
description: This is a description of my new guide
---
Hello World!

Starlight uses the frontmatter of the Markdown file to generate the navigation and other metadata for the guide. On Github this will appear as a small table at the top of the file so your guide will still be readable in the repository.

Now you can add content to the guide using Markdown. Starlight supports all the standard Markdown features, including headings, lists, links, images, and code blocks. You can also use MDX to embed JavaScript, Components, and other features directly into your Markdown files. This allows you to create interactive components and dynamic content within your guides.

You can see a full list of the supported features in the Starlight documentation.

MDX

MDX is a superset of Markdown that allows you to use JSX components within your Markdown file. This means that you can do things such as importing reusable components. One component that is/should be used frequently is the Contact component, which adds a small little note explaining some ways of getting help from the RIOT community. This component is imported like this:

doc/guides/test/hello_world.mdx
import Contact from '@components/contact.astro';
<Contact/>

Placing the guide

One last manual step is to add the new guide to the navigation. This is done in the doc/starlight/astro.config.mjs file.

Compared to the Doxygen output we want to be extremely careful about the navigation and only show the guides that are relevant to the user and in a logical order that does not overwhelm the user with too many options at once.

Generally, the less information you declare within the config the better, given that ideally your frontmatter information is enough to generate the navigation.

You can either add your guide to an existing section or create a new section. In the event that you want to simply append your guide to an existing section, you can simply add the file name to the list of files in the section. The root of the so called slug of your file is the guides folder itself, so a guide under doc/guides/test/hello_world.md will have the slug test/hello_world.md.

Creating a new section

Generally, we want to avoid creating new sections unless absolutely necessary. For example, if you create a totally new tutorial that spans multiple files, it might make sense to create a new section. In this case, you can create a new section by adding a new entry to the sidebar array in the astro.config.mjs file. The entry should look like this:

doc/starlight/astro.config.mjs
sidebar: [
{
label: "The Best Tutorial",
items: [
"tutorial/best_tutorial",
],
},
],

Code Block Testing

If you are writing a guide that includes code blocks it is important to test them to make sure they work as expected. To facilitate this, we have a small script that runs over the code blocks in the guide and compares them to a specified example folder.

You can also utilize this script to test your code blocks locally before pushing them to the repository. To do this, you need to run the following command:

Running the code block testing script
./dist/tools/code_in_guides_check/check_for_code.sh

For example, let’s say that we have a tutorial that explains the hello world example. This example is located in examples/basic/hello-world/ and the guide is located in doc/guides/test/hello_world.md.

First we have to tell the script where to find the example folder. This is done by adding the code_folder key to the frontmatter of the guide. The value should be the path to the example folder relative to the root of the repository.

Example guide with code_folder
---
title: Tutorial Hello World
description: This is a description of my new guide
code_folder: examples/basic/hello-world/
---

Then we can add the code blocks to the guide. The script will automatically detect the code blocks and run them against the example folder.

This code block will be tested against the hello world example
```c
int main(void)
{
puts("Hello World!");
```

In the case that you want to skip the code block testing, you can add the <!--skip ci--> comment one line above the code block. The script will ignore this code block and not run it against the example folder.

This code block will be ignored by the script
<!--skip ci-->
```c
int not_main(void)
{
puts("Goodbye World!");
```