Intermediate and Advanced Astro + Starlight Tutorial

A practical guide for building maintainable documentation, lesson, reference, and worldbuilding sites with Astro and Starlight.

What This Tutorial Covers

This tutorial assumes you already know the basic Astro and Starlight workflow:

npm create astro@latest
npx astro add starlight
npm run dev
npm run build

Now the goal is to move beyond a simple docs site and learn how to organize a serious project with reusable structure, content strategy, custom components, deployment settings, and troubleshooting habits.

The Big Picture

Astro is useful when your site is mostly content, but you still want modern tooling. Starlight is a documentation framework built on Astro. Together, they are a strong choice for:

The mental model is simple:

Markdown or MDX files = content
Astro components = reusable page pieces
Starlight config = docs structure and navigation
Astro build = final static website

Recommended Project Structure

A serious Starlight site should be organized intentionally. A common structure looks like this:

my-starlight-site/
  astro.config.mjs
  package.json
  public/
    favicon.svg
    images/
  src/
    assets/
    components/
      CalloutBox.astro
      LessonCard.astro
      CharacterCard.astro
      TimelineList.astro
    content/
      docs/
        index.md
        getting-started.md
        lessons/
        reference/
        worldbuilding/
    styles/
      custom.css

Starlight expects most documentation pages to live inside:

src/content/docs/

That folder becomes the backbone of the site. The file and folder names inside it help determine page URLs and sidebar structure.

Configuring Starlight in astro.config.mjs

The main Starlight configuration usually lives inside astro.config.mjs. This is where you control the site title, description, sidebar, social links, plugins, custom CSS, and other global settings.

import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';

export default defineConfig({
  integrations: [
    starlight({
      title: 'My Knowledge Site',
      description: 'Lessons, references, and project notes.',
      sidebar: [
        {
          label: 'Start Here',
          items: [
            { label: 'Introduction', slug: 'intro' },
            { label: 'Project Setup', slug: 'project-setup' }
          ]
        },
        {
          label: 'Lessons',
          autogenerate: { directory: 'lessons' }
        },
        {
          label: 'Reference',
          autogenerate: { directory: 'reference' }
        }
      ],
      customCss: ['./src/styles/custom.css']
    })
  ]
});

For a small site, manual sidebar links are fine. For a larger site, autogenerated sidebar sections save time and reduce broken navigation.

Sidebar Strategy

Intermediate and advanced Starlight projects need a sidebar strategy. Do not let the sidebar become a junk drawer.

A good sidebar usually has a few clear groups:

Start Here
Lessons
Guides
Reference
Examples
Appendix

For a worldbuilding site, the groups might be:

World Overview
Regions
Characters
Factions
Locations
Storylines
Timeline
Reference

For a course or lesson site, the groups might be:

Course Introduction
Core Lessons
Practice Projects
Reference Sheets
Troubleshooting
Next Steps

Using Frontmatter Well

Markdown pages in Starlight use frontmatter at the top of the file. Frontmatter is metadata about the page.

---
title: "Working with Astro Components"
description: "Learn how reusable Astro components improve a Starlight site."
sidebar:
  label: "Astro Components"
  order: 3
---

# Working with Astro Components

Page content goes here.

Useful frontmatter can include:

Markdown vs MDX

Use regular Markdown for most pages. Use MDX when a page needs interactive or reusable components.

Use Markdown When... Use MDX When...
The page is mostly text, headings, lists, and code blocks. The page needs Astro, React, Vue, Svelte, or custom components.
You want simple authoring. You want reusable visual cards, tabs, maps, lesson widgets, or diagrams.
The page is a reference article. The page behaves like a mini application or enhanced lesson.

Example MDX usage:

---
title: "Lesson with a Custom Card"
---

import LessonCard from '../../components/LessonCard.astro';

# Lesson with a Custom Card

<LessonCard title="Practice Project" level="Intermediate" />

Creating Reusable Astro Components

Reusable components are one of the main reasons to move beyond hand-coded HTML. They keep repeated content consistent.

Example component:

---
const { title, level, description } = Astro.props;
---

<article class="lesson-card">
  <h3>{title}</h3>
  <p><strong>Level:</strong> {level}</p>
  <p>{description}</p>
</article>

Then use it in an MDX file:

import LessonCard from '../../components/LessonCard.astro';

<LessonCard
  title="Deploying a Starlight Site"
  level="Intermediate"
  description="Learn how build output, routes, and hosting settings work."
/>

Custom CSS Without Fighting Starlight

Starlight already provides a strong visual foundation. Instead of replacing everything, start with small custom improvements.

In astro.config.mjs:

starlight({
  title: 'My Docs',
  customCss: ['./src/styles/custom.css']
})

Then create:

src/styles/custom.css

Example:

.lesson-card {
  border: 1px solid var(--sl-color-gray-5);
  border-radius: 0.75rem;
  padding: 1rem;
  margin: 1rem 0;
}

.lesson-card h3 {
  margin-top: 0;
}

Best practice: add custom styles for your own classes first. Avoid deeply overriding Starlight internals unless you have a specific reason.

Content Collections and Structured Content

Astro content collections help manage structured content with schemas and type safety. Starlight already uses a docs collection, but you can also create additional collections for data-like content.

For example, a lesson collection could describe lessons with required metadata:

// src/content.config.ts
import { defineCollection, z } from 'astro:content';

const lessons = defineCollection({
  schema: z.object({
    title: z.string(),
    level: z.enum(['beginner', 'intermediate', 'advanced']),
    order: z.number(),
    topics: z.array(z.string()).optional()
  })
});

export const collections = { lessons };

This is useful when you want Astro to validate your content. For example, if every lesson must have a level, the schema can enforce that.

Advanced Pattern: Index Pages Generated from Content

Instead of manually maintaining a list of lessons, you can generate an index page from a collection.

---
import { getCollection } from 'astro:content';

const lessons = await getCollection('lessons');
const sortedLessons = lessons.sort((a, b) => a.data.order - b.data.order);
---

<h1>Lesson Index</h1>

<ul>
  {sortedLessons.map((lesson) => (
    <li>
      <a href={`/lessons/${lesson.id}/`}>{lesson.data.title}</a>
      <span> - {lesson.data.level}</span>
    </li>
  ))}
</ul>

This pattern is powerful for lesson libraries, character indexes, reference pages, bestiaries, timelines, and project archives.

Advanced Pattern: A Worldbuilding Index

For a worldbuilding site, you could create structured collections for characters, locations, factions, or storylines.

const characters = defineCollection({
  schema: z.object({
    title: z.string(),
    region: z.string(),
    faction: z.string().optional(),
    role: z.string(),
    status: z.enum(['active', 'missing', 'dead', 'unknown']).optional()
  })
});

Then each character file has consistent metadata:

---
title: "Example Character"
region: "Europe"
faction: "House Example"
role: "Diplomat"
status: "active"
---

## Identity

## Background

## Relationships

## Story Use

This lets the site generate character lists, region indexes, faction pages, and cross-reference pages.

Using Built-In Starlight Features

Starlight gives you many features without requiring you to build them manually:

Before building your own version of a feature, check whether Starlight already provides it.

Adding Diagrams

For lessons and worldbuilding, diagrams are often helpful. You can use Mermaid, SVG, or custom Astro components.

For Mermaid, one approach is to create a component that safely renders Mermaid blocks. A simple component might look like this:

---
const { chart } = Astro.props;
---

<pre class="mermaid">{chart}</pre>

<script type="module">
  import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
  mermaid.initialize({ startOnLoad: true });
</script>

For production, consider loading Mermaid once globally instead of importing it on every page.

Adding React or Other Interactive Components

Astro lets you use interactive components only when needed. This is one of its biggest advantages.

Example use cases:

Example hydration pattern:

<CharacterFilter client:load />

Common hydration directives include:

Use the lightest option that solves the problem. A static page does not need a hydrated component.

Intermediate Deployment Knowledge

For a static Starlight site, the normal build command is:

npm run build

The default output folder is usually:

dist

Common host settings:

Host Build Command Publish / Output Directory
Netlify npm run build dist
Vercel npm run build dist
Cloudflare Pages npm run build dist
GitHub Pages GitHub Actions workflow dist

GitHub Pages Base Path Warning

If you deploy to a GitHub Pages project URL, your site may live at a path like:

https://username.github.io/repository-name/

In that case, you may need to configure site and base in astro.config.mjs:

export default defineConfig({
  site: 'https://username.github.io',
  base: '/repository-name',
  integrations: [starlight({ title: 'My Docs' })]
});

If the site works locally but assets break on GitHub Pages, check the base path first.

Performance Best Practices

Astro and Starlight are already performance-oriented, but larger sites still need discipline.

Content Maintenance Strategy

Advanced Astro/Starlight work is not only about code. It is also about maintaining a growing content library.

Use consistent file names:

good-file-name.md
another-clear-file-name.md
not This Random File Name.md

Use consistent folder names:

lessons/
reference/
projects/
worldbuilding/
characters/
factions/
locations/

Use consistent page templates:

Overview
Concept
Example
Walkthrough
Common Mistakes
Practice
Summary

Consistency matters more as the site grows.

Common Problems and Fixes

Problem: The sidebar page order is wrong

Fix it with frontmatter:

---
title: "Advanced Components"
sidebar:
  order: 5
---

Problem: A page does not appear in the sidebar

Check the file location, sidebar configuration, and whether the page is inside the expected docs directory.

Problem: MDX import fails

Check the relative path and make sure the MDX integration is installed if needed.

Problem: Deployment works but images are broken

Check whether images are in public/ or imported from src/assets/. Also check the site base path if deploying under a subdirectory.

Problem: Build works locally but fails on the host

Check Node version, lockfile consistency, missing environment variables, and case-sensitive file names.

Suggested Intermediate Practice Project

Build a Starlight site with these sections:

Start Here
Lessons
Reference
Examples
Troubleshooting

Add at least:

Suggested Advanced Practice Project

Build a reference site with structured collections:

characters
locations
factions
lessons
references

Then create:

This project teaches you the real value of Astro: content is not just pages; content can become structured data that generates pages, indexes, and navigation.

Advanced Mental Model

Beginner Astro thinking:

I write pages and Astro publishes them.

Intermediate Astro thinking:

I write reusable layouts and components so pages stay consistent.

Advanced Astro thinking:

I model my content as structured data, then generate pages, indexes, navigation, and references from that data.

When Astro + Starlight Is the Right Tool

Astro + Starlight is a strong choice when the project is mostly content and reference material.

Use it for:

Consider another framework when the project is mostly a full application:

Checklist

Before calling a Starlight project maintainable, check the following:

Summary

Astro + Starlight starts simple, but it scales well when you treat it as a content system instead of a pile of pages. The core skills are:

The more your site grows, the more valuable Astro becomes. A single reusable component or schema can save dozens of future edits.