What You Are Learning
This tutorial focuses on two important parts of an Astro Starlight project:
- Project structure: where files go and what the major folders do.
- Sidebar navigation: how Starlight decides what appears in the navigation sidebar.
These two topics matter because Starlight sites are usually content-heavy. Once you have many lesson pages, worldbuilding pages, character files, reference notes, or technical guides, structure and navigation become the difference between a useful site and a confusing pile of pages.
The Big Picture
Starlight is an Astro integration for documentation-style websites. Astro handles the site build system, routing, assets, and page rendering. Starlight adds documentation features such as a sidebar, search, page layout, table of contents, and Markdown/MDX-friendly authoring.
Astro project
↓
Starlight integration
↓
Markdown and MDX documentation pages
↓
Sidebar, search, page layout, and static site output
For most projects, your everyday work will happen in these places:
src/content/docs/ documentation pages
src/components/ reusable components
src/assets/ source-managed images and assets
public/ static files copied directly to the final site
astro.config.mjs main Astro and Starlight configuration
Starting Point: Create a Starlight Project
The common setup command is:
npm create astro@latest
During setup, choose a documentation/Starlight starter if offered. Another common approach is to create an Astro project first, then add Starlight:
npx astro add starlight
Then run the development server:
npm run dev
Build the production site with:
npm run build
The finished static site is usually generated into:
dist/
Typical Starlight Project Structure
A small Starlight project may look like this:
my-starlight-site/
public/
favicon.svg
src/
assets/
content/
docs/
index.md
getting-started.md
components/
astro.config.mjs
package.json
tsconfig.json
A larger project might look like this:
my-starlight-site/
public/
favicon.png
images/
maps/
diagrams/
src/
assets/
logo.svg
components/
CharacterCard.astro
InfoBox.astro
LessonObjectives.astro
content/
docs/
index.md
getting-started.md
worldbuilding/
index.md
regions/
europe.md
austral-confluence.md
characters/
character-template.md
example-character.md
lessons/
index.md
markdown-basics.md
mdx-basics.mdx
reference/
yaml.md
deployment.md
styles/
custom.css
astro.config.mjs
package.json
tsconfig.json
The main idea is simple: content goes in src/content/docs/. The folder structure inside docs often becomes your site structure and sidebar structure.
The public Folder
The public/ folder is for static files that should be copied directly to the final website without being processed by Astro.
public/
favicon.png
images/
map.png
character-portrait.png
downloads/
world-bible-template.pdf
Files in public/ are referenced from the site root.

Use public/ for simple static assets such as favicons, downloadable files, screenshots, and images you want to reference by direct path.
The src/assets Folder
The src/assets/ folder is for assets managed by Astro's build pipeline. This is often useful for logos, imported images, or files used directly by components.
src/
assets/
logo.svg
hero-image.png
For beginner documentation sites, you can often start with public/. As the site grows, src/assets/ becomes more useful for optimized or component-driven assets.
The src/content/docs Folder
This is the heart of a Starlight site. Documentation pages live in:
src/content/docs/
Example:
src/content/docs/index.md
src/content/docs/getting-started.md
src/content/docs/lessons/markdown-basics.md
src/content/docs/worldbuilding/character-template.md
Each Markdown or MDX file becomes a page in the docs site.
src/content/docs/index.md
→ /
src/content/docs/getting-started.md
→ /getting-started/
src/content/docs/lessons/markdown-basics.md
→ /lessons/markdown-basics/
src/content/docs/worldbuilding/character-template.md
→ /worldbuilding/character-template/
Markdown and MDX Files
Most pages can be plain Markdown:
example-page.md
Use MDX when the page needs components:
interactive-example.mdx
Markdown is best for normal writing. MDX is best for pages that need custom cards, stat blocks, callouts, tabs, visual components, or interactive examples.
Basic Page Frontmatter
Every Starlight page usually begins with frontmatter. Frontmatter is YAML metadata at the top of a Markdown or MDX file.
---
title: "Getting Started"
description: "Learn how this documentation site is organized."
---
# Getting Started
This page introduces the project.
The title is especially important because Starlight can use it for page headings, browser metadata, and sidebar labels.
The astro.config.mjs File
The main Starlight configuration lives in astro.config.mjs.
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Documentation Site',
}),
],
});
This is where you configure the site title, logo, sidebar, social links, custom CSS, table of contents behavior, plugins, and other Starlight options.
Adding Custom CSS
For simple customization, create a CSS file:
src/styles/custom.css
Then register it in astro.config.mjs:
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Documentation Site',
customCss: ['./src/styles/custom.css'],
}),
],
});
This keeps custom styling separate from your Markdown content.
How Starlight Sidebar Navigation Works
Starlight can build sidebar navigation in two main ways:
- Autogenerated sidebar: Starlight builds the sidebar from your folder structure.
- Manual sidebar: You define sidebar groups and items yourself in
astro.config.mjs.
For small or early projects, autogenerated navigation is often enough. For larger lesson libraries, world bibles, or professional docs, manual navigation gives more control.
Autogenerated Sidebar
By default, Starlight can generate the sidebar based on files and folders in src/content/docs/. For example:
src/content/docs/
index.md
getting-started.md
lessons/
markdown-basics.md
mdx-basics.md
worldbuilding/
character-template.md
region-template.md
This can create a sidebar similar to:
Getting Started
Lessons
Markdown Basics
MDX Basics
Worldbuilding
Character Template
Region Template
The advantage is speed. You add files and Starlight finds them.
The disadvantage is that folder names, file names, and page titles need to be carefully managed or the sidebar can become messy.
Manual Sidebar
Manual sidebar navigation is configured in astro.config.mjs.
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Documentation Site',
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Introduction', slug: 'intro' },
{ label: 'Getting Started', slug: 'getting-started' },
],
},
{
label: 'Lessons',
items: [
{ label: 'Markdown Basics', slug: 'lessons/markdown-basics' },
{ label: 'MDX Basics', slug: 'lessons/mdx-basics' },
],
},
],
}),
],
});
The label is what appears in the sidebar. The slug points to the page route.
Slug Basics
A slug is the URL path to a page without the leading slash.
src/content/docs/getting-started.md
slug: 'getting-started'
src/content/docs/lessons/markdown-basics.md
slug: 'lessons/markdown-basics'
src/content/docs/worldbuilding/characters/example-character.md
slug: 'worldbuilding/characters/example-character'
If a sidebar item points to the wrong slug, the link will be broken.
Sidebar Groups
A sidebar group collects related pages under a heading.
sidebar: [
{
label: 'Worldbuilding',
items: [
{ label: 'World Bible Overview', slug: 'worldbuilding/overview' },
{ label: 'Character Template', slug: 'worldbuilding/character-template' },
{ label: 'Region Template', slug: 'worldbuilding/region-template' },
],
},
]
For lesson sites, groups could be courses or difficulty levels.
Beginner Lessons
Intermediate Lessons
Advanced Lessons
Reference
For worldbuilding sites, groups could be content categories.
World Overview
Regions
Characters
Factions
Locations
Storylines
Timeline
Reference
Nested Sidebar Groups
For larger sites, groups can be nested.
sidebar: [
{
label: 'Worldbuilding',
items: [
{
label: 'Regions',
items: [
{ label: 'Europe', slug: 'worldbuilding/regions/europe' },
{ label: 'Austral Confluence', slug: 'worldbuilding/regions/austral-confluence' },
],
},
{
label: 'Characters',
items: [
{ label: 'Character Template', slug: 'worldbuilding/characters/template' },
{ label: 'Example Character', slug: 'worldbuilding/characters/example-character' },
],
},
],
},
]
Nested groups are powerful, but too many levels can make the sidebar harder to use. Two levels is usually comfortable. Three levels should be used carefully.
Autogenerated Groups Inside Manual Sidebar
A useful middle path is to define the major groups manually, but let Starlight autogenerate the pages inside a folder.
sidebar: [
{
label: 'Lessons',
autogenerate: { directory: 'lessons' },
},
{
label: 'Worldbuilding',
autogenerate: { directory: 'worldbuilding' },
},
]
This gives you control over the big categories while avoiding the need to manually list every page.
Recommended Structure for a Lesson Site
For a lesson library, use folders that match how a learner thinks.
src/content/docs/
index.md
lessons/
index.md
beginner/
html-basics.md
css-basics.md
javascript-basics.md
intermediate/
markdown-mdx.md
astro-components.md
starlight-sidebar.md
advanced/
content-collections.md
custom-components.mdx
deployment-workflow.md
reference/
glossary.md
commands.md
troubleshooting.md
Possible sidebar:
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Home', slug: '' },
{ label: 'How to Use This Site', slug: 'lessons' },
],
},
{
label: 'Beginner Lessons',
autogenerate: { directory: 'lessons/beginner' },
},
{
label: 'Intermediate Lessons',
autogenerate: { directory: 'lessons/intermediate' },
},
{
label: 'Advanced Lessons',
autogenerate: { directory: 'lessons/advanced' },
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
},
]
Recommended Structure for a World Bible Site
For a world bible, use folders that match the types of entries you will create again and again.
src/content/docs/
index.md
world/
overview.md
timeline.md
technology.md
regions/
index.md
europe.md
austral-confluence.md
atlantic-compact.md
characters/
index.md
character-template.md
example-character.md
factions/
index.md
faction-template.md
locations/
index.md
location-template.md
storylines/
index.md
storyline-template.md
reference/
glossary.md
naming-conventions.md
Possible sidebar:
sidebar: [
{
label: 'World Overview',
items: [
{ label: 'Home', slug: '' },
{ label: 'Overview', slug: 'world/overview' },
{ label: 'Timeline', slug: 'world/timeline' },
{ label: 'Technology', slug: 'world/technology' },
],
},
{
label: 'Regions',
autogenerate: { directory: 'regions' },
},
{
label: 'Characters',
autogenerate: { directory: 'characters' },
},
{
label: 'Factions',
autogenerate: { directory: 'factions' },
},
{
label: 'Locations',
autogenerate: { directory: 'locations' },
},
{
label: 'Storylines',
autogenerate: { directory: 'storylines' },
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
},
]
Page Ordering
Navigation order matters. A sidebar should teach the reader where to start and what to read next.
For manual sidebars, the order is the order you write in astro.config.mjs.
items: [
{ label: 'Introduction', slug: 'intro' },
{ label: 'Installation', slug: 'installation' },
{ label: 'Project Structure', slug: 'project-structure' },
{ label: 'Sidebar Navigation', slug: 'sidebar-navigation' },
]
For autogenerated sidebars, file and folder names become more important. If you need strict ordering, manual sidebar configuration is usually clearer.
Index Pages
Each major folder should usually have an index.md page.
src/content/docs/lessons/index.md
src/content/docs/worldbuilding/index.md
src/content/docs/characters/index.md
An index page acts like a section landing page. It can explain what the section contains and link to important pages.
---
title: "Characters"
description: "Character profiles, character templates, and major figures."
---
# Characters
This section contains character profiles and reusable templates.
## Start Here
- [Character Template](/characters/character-template/)
- [Example Character](/characters/example-character/)
Good Sidebar Labels
Good sidebar labels are short, clear, and predictable.
| Weak Label | Better Label |
|---|---|
| Stuff | Reference |
| People Things | Characters |
| Places and Such | Locations |
| How It All Works Maybe | System Rules |
| Misc Notes | Glossary |
Manual vs Autogenerated Sidebar
| Approach | Best For | Tradeoff |
|---|---|---|
| Autogenerated | Small sites, quick starts, simple folder structures | Less precise control |
| Manual | Polished docs, lesson paths, curated world bibles | More maintenance |
| Hybrid | Growing sites with large categories | Requires thoughtful folder structure |
For most serious projects, the hybrid approach is the best long-term choice.
Hybrid Sidebar Pattern
This pattern works well when you want major categories in a deliberate order but do not want to manually list every page.
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Introduction', slug: '' },
{ label: 'How to Use This Site', slug: 'getting-started' },
],
},
{
label: 'Lessons',
autogenerate: { directory: 'lessons' },
},
{
label: 'World Bible',
autogenerate: { directory: 'worldbuilding' },
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
},
]
This is usually easier to maintain than a fully manual sidebar.
Example: Complete astro.config.mjs
Here is a practical example for a combined lesson and world bible site:
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
site: 'https://example.com',
integrations: [
starlight({
title: 'World Bible and Lessons',
customCss: ['./src/styles/custom.css'],
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Home', slug: '' },
{ label: 'Getting Started', slug: 'getting-started' },
],
},
{
label: 'Lessons',
autogenerate: { directory: 'lessons' },
},
{
label: 'World Bible',
items: [
{ label: 'Overview', slug: 'world/overview' },
{ label: 'Timeline', slug: 'world/timeline' },
{
label: 'Reference Sections',
items: [
{ label: 'Regions', slug: 'regions' },
{ label: 'Characters', slug: 'characters' },
{ label: 'Factions', slug: 'factions' },
{ label: 'Locations', slug: 'locations' },
],
},
],
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
},
],
}),
],
});
Common Sidebar Mistakes
Broken slugs
A sidebar item must point to an existing page.
Bad:
{ label: 'Markdown Basics', slug: 'markdown-basics' }
If the real file is:
src/content/docs/lessons/markdown-basics.md
Better:
{ label: 'Markdown Basics', slug: 'lessons/markdown-basics' }
Too many top-level groups
If everything is top-level, nothing feels organized. Group related pages together.
Too much nesting
If a reader has to open four levels of navigation to find a page, the site is probably too deeply nested.
Vague labels
Labels should tell the reader exactly what section they are entering.
Common Project Structure Mistakes
Putting docs pages in the wrong folder
Wrong:
src/pages/lesson-one.md
Usually correct for Starlight docs:
src/content/docs/lesson-one.md
Mixing unrelated content in one folder
Messy:
src/content/docs/
europe.md
markdown-basics.md
veritas.md
css-basics.md
glossary.md
Better:
src/content/docs/
regions/europe.md
lessons/markdown-basics.md
characters/veritas.md
lessons/css-basics.md
reference/glossary.md
Skipping index pages
Folders without index pages can feel like drawers without labels. Add a section landing page for each major folder.
Practical Build Plan
When starting a new Starlight site, build in this order:
- Create the project.
- Add or confirm Starlight.
- Create the major folders under
src/content/docs/. - Add
index.mdpages for each major section. - Add a few sample pages.
- Use autogenerated sidebar first.
- Switch to manual or hybrid sidebar when the structure becomes clear.
- Add custom CSS only after the content structure works.
- Run
npm run buildto catch broken links or configuration problems.
Practice Exercise: Create a Lesson Section
Create this folder structure:
src/content/docs/
lessons/
index.md
markdown-basics.md
mdx-basics.md
Create lessons/index.md:
---
title: "Lessons"
description: "Tutorials and learning paths."
---
# Lessons
This section contains tutorials and learning guides.
## Start Here
- [Markdown Basics](/lessons/markdown-basics/)
- [MDX Basics](/lessons/mdx-basics/)
Add this sidebar group:
{
label: 'Lessons',
autogenerate: { directory: 'lessons' },
}
Practice Exercise: Create a World Bible Section
Create this folder structure:
src/content/docs/
world/
overview.md
timeline.md
characters/
index.md
character-template.md
regions/
index.md
region-template.md
Add this sidebar configuration:
sidebar: [
{
label: 'World',
items: [
{ label: 'Overview', slug: 'world/overview' },
{ label: 'Timeline', slug: 'world/timeline' },
],
},
{
label: 'Characters',
autogenerate: { directory: 'characters' },
},
{
label: 'Regions',
autogenerate: { directory: 'regions' },
},
]
Troubleshooting
The page exists but does not appear in the sidebar
Check whether you are using a manual sidebar. If the sidebar is manual, Starlight will not automatically show every new page unless you add it or use an autogenerated group.
The sidebar link goes to a 404 page
Check the slug. The slug should match the route created by the file path under src/content/docs/.
The sidebar order is wrong
Use a manual sidebar for strict order. Autogenerated sidebars are convenient, but manual sidebars are better for carefully designed reading paths.
The site builds locally but assets are missing
Check whether the files are in public/ and referenced with root paths like /images/example.png.
Recommended Naming Conventions
Pick one naming style and stay consistent.
Good:
markdown-basics.md
character-template.md
world-bible-overview.md
Also acceptable:
markdown_basics.md
character_template.md
world_bible_overview.md
Avoid:
Markdown Basics FINAL New.md
character template copy 2.md
For web routes, hyphenated names are common because they produce readable URLs.
Cheat Sheet
| Thing | Where It Usually Goes |
|---|---|
| Documentation page | src/content/docs/ |
| Markdown page | src/content/docs/example.md |
| MDX page | src/content/docs/example.mdx |
| Reusable component | src/components/ |
| Custom CSS | src/styles/custom.css |
| Static images/downloads | public/ |
| Main Starlight config | astro.config.mjs |
| Production output | dist/ |
Simple Rule of Thumb
Use folders to organize meaning.
Use frontmatter to describe pages.
Use the sidebar to guide readers.
Use manual navigation when order matters.
Use autogenerated navigation when volume matters.
Use index pages to explain each section.
What to Learn Next
- Starlight customization and custom CSS
- MDX components in Starlight pages
- Astro content collections and schemas
- Starlight search and page metadata
- Mermaid diagrams inside Astro/Starlight
- Deploying Starlight to Vercel, Netlify, or Cloudflare Pages
- Building a full world bible structure
- Building a full lesson library structure