What You Are Learning
This tutorial explains how to customize an Astro Starlight site at three levels:
- Configuration customization: change built-in Starlight options such as title, logo, social links, table of contents, and edit links.
- CSS customization: change colors, spacing, typography, and visual details with custom CSS.
- Component overrides: replace or extend Starlight’s internal UI components when configuration and CSS are not enough.
The goal is to customize safely. Start with the least invasive option, then move to component overrides only when you need deeper control.
The Big Idea
Starlight gives you a polished documentation interface by default. You can change a lot without replacing major parts of the system.
Small visual change?
Use custom CSS.
Built-in feature setting?
Use astro.config.mjs.
Need to replace part of the Starlight UI?
Use a component override.
Think of it like remodeling a house:
- Configuration is rearranging furniture.
- CSS is repainting the walls.
- Component overrides are rebuilding part of the room.
Recommended Customization Order
Before overriding a Starlight component, try these approaches in order:
- Use page frontmatter.
- Use Starlight configuration in
astro.config.mjs. - Use custom CSS.
- Use MDX or Astro components inside your content.
- Override a Starlight component only when the earlier options cannot solve the problem.
This order keeps your site easier to upgrade and maintain.
Project Structure for Customization
A customized Starlight project might use this structure:
my-starlight-site/
public/
favicon.png
images/
src/
assets/
light-logo.svg
dark-logo.svg
components/
CharacterCard.astro
LessonObjectives.astro
overrides/
SiteTitle.astro
PageTitle.astro
Footer.astro
styles/
custom.css
content/
docs/
index.md
getting-started.md
astro.config.mjs
package.json
You do not have to use an overrides folder, but it is a clean convention. It makes it obvious which files are replacing Starlight internals.
Level One: Configuration Customization
Many customizations belong in astro.config.mjs. This file controls Astro and Starlight settings.
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My World Bible',
}),
],
});
Use configuration when you want to change official Starlight options such as title, sidebar, logo, social links, page layout behavior, table of contents, or custom CSS registration.
Adding a Logo
Add logo files to src/assets/:
src/assets/light-logo.svg
src/assets/dark-logo.svg
Then configure the logo:
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My World Bible',
logo: {
light: './src/assets/light-logo.svg',
dark: './src/assets/dark-logo.svg',
},
}),
],
});
If your logo image already contains the site title, you can visually hide the text title while keeping it available for screen readers:
logo: {
src: './src/assets/logo.svg',
replacesTitle: true,
}
Customizing the Page Layout with Frontmatter
For a special landing page, use Starlight’s template: splash frontmatter option.
---
title: "World Bible Home"
template: splash
---
# World Bible Home
Welcome to the setting archive.
This is useful for homepages, course landing pages, or large visual index pages. Use this before trying to override layout components.
Customizing the Table of Contents
Starlight normally displays a table of contents based on page headings. For some pages, you may want to reduce or disable it.
---
title: "Landing Page"
tableOfContents: false
---
Use this for pages where the normal right-side page navigation is not helpful, such as a homepage, gallery, or custom index.
Level Two: Custom CSS
Custom CSS is the safest way to change the look of a Starlight site.
Create:
src/styles/custom.css
Register it in astro.config.mjs:
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Custom Docs',
customCss: ['./src/styles/custom.css'],
}),
],
});
Now your CSS file can customize theme variables and page styling.
Theme Variables
Starlight exposes CSS custom properties that can be changed in your custom CSS file.
:root {
--sl-font: system-ui, sans-serif;
--sl-content-width: 48rem;
--sl-text-5xl: 3rem;
}
Exact variable names may change as Starlight evolves, so always check the current Starlight CSS and styling documentation when making deep visual changes.
Styling Custom Content Components
If you create your own components, style them with classes in your custom CSS.
/* src/styles/custom.css */
.character-card {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.75rem;
padding: 1rem;
margin: 1rem 0;
}
Then use that class in an Astro component:
---
const { name, role } = Astro.props;
---
<aside class="character-card">
<h2>{name}</h2>
<p>{role}</p>
</aside>
This approach is safer than overriding Starlight’s built-in UI.
Level Three: Content Components
Before replacing Starlight internals, ask whether you only need a reusable content block.
Examples:
- Character stat card
- Faction summary box
- Lesson objectives box
- Warning callout
- Timeline entry
- World bible metadata panel
These belong in src/components/, not necessarily in Starlight overrides.
Example: Lesson Objectives Component
Create:
src/components/LessonObjectives.astro
Add:
---
const { title = 'Lesson Objectives' } = Astro.props;
---
<aside class="lesson-objectives">
<h2>{title}</h2>
<slot />
</aside>
Use it in an MDX page:
---
title: "Markdown Basics"
---
import LessonObjectives from '../../components/LessonObjectives.astro';
# Markdown Basics
<LessonObjectives>
- Understand headings
- Write lists
- Add links
- Add code blocks
</LessonObjectives>
This adds a custom block without changing Starlight itself.
Level Four: Component Overrides
Component overrides are for changing Starlight’s built-in interface. Starlight supports overriding built-in components by pointing component names to your replacement files in the Starlight components configuration option.
starlight({
title: 'My Custom Docs',
components: {
SiteTitle: './src/overrides/SiteTitle.astro',
},
})
This tells Starlight, “When you would normally render SiteTitle, use my file instead.”
When to Override a Component
Override a Starlight component when you need to change behavior or markup that CSS cannot reasonably change.
| Goal | Best Tool |
|---|---|
| Change colors | Custom CSS |
| Add a logo | Starlight config |
| Add a reusable stat card inside content | Custom Astro component |
| Change the site title link behavior | Component override |
| Replace the footer markup | Component override |
| Change page sidebar behavior | Component override |
Basic Override Setup
Create an override folder:
src/overrides/
Create a replacement component:
src/overrides/SiteTitle.astro
Register it in astro.config.mjs:
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Custom Docs',
components: {
SiteTitle: './src/overrides/SiteTitle.astro',
},
}),
],
});
Example: Override SiteTitle
A simple custom SiteTitle might look like this:
---
import type { Props } from '@astrojs/starlight/props';
const { siteTitle } = Astro.props;
---
<a class="custom-site-title" href="/">
<span class="custom-site-title__mark">◆</span>
<span>{siteTitle}</span>
</a>
Then style it:
.custom-site-title {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-weight: 700;
text-decoration: none;
}
.custom-site-title__mark {
font-size: 1.25rem;
}
This is useful if you want the site title to have special markup, icon text, or different link behavior.
Important: Check the Override Reference
Do not guess component names. Starlight has an overrides reference that lists the components available to override.
Common kinds of override targets include:
- Header and site title components
- Sidebar-related components
- Page title and content layout components
- Footer components
- Table of contents components
- Search-related components
Component names and APIs can change over time, so always compare your override with the current Starlight implementation.
Extending Instead of Replacing
Sometimes you do not want to fully replace a component. You want to reuse the default component and wrap it with extra markup.
Conceptually, this looks like:
---
import DefaultComponent from '@astrojs/starlight/components/SomeComponent.astro';
---
<div class="custom-wrapper">
<DefaultComponent {...Astro.props} />
<p>Extra custom content</p>
</div>
This approach can be safer than rewriting everything from scratch, but the exact import path depends on Starlight’s current exports and documentation.
Common Override Example Ideas
Custom footer
Use this when you want world bible copyright notes, project version, contact links, or deployment metadata.
Custom site title
Use this when the site title should link somewhere special or include custom branding markup.
Custom page title
Use this when you want to display page metadata under titles, such as lesson level, region, character type, or last updated date.
Custom sidebar or table of contents
Use this only when you need different navigation behavior. Sidebar overrides can become complex because they affect how readers move through the entire site.
World Bible Use Cases
For a world bible, component overrides can help make Starlight feel less like generic software documentation.
| Need | Suggested Approach |
|---|---|
| Custom character stat panels | MDX content component |
| Faction badges in page title area | Page title override or content component |
| Region-themed landing page | template: splash plus custom components |
| Footer with canon/version notes | Footer override |
| Different sidebar behavior for lore sections | Sidebar override, used carefully |
Lesson Site Use Cases
For a lesson or tutorial site, customizations usually support learning flow.
| Need | Suggested Approach |
|---|---|
| Lesson objectives box | MDX content component |
| Difficulty badge under page title | Page title override or frontmatter-aware component |
| Course landing page | template: splash plus cards |
| Custom footer with next steps | Footer override or content component |
| Custom navigation by course level | Sidebar config first, override only if needed |
Example: Page Metadata Display
For lesson or world bible pages, you may want visible metadata:
---
title: "Markdown Basics"
level: "Beginner"
section: "Writing Formats"
status: "Draft"
---
Before overriding Starlight’s page title, consider adding a normal MDX component at the top of the page:
import PageMeta from '../../components/PageMeta.astro';
<PageMeta level={frontmatter.level} section={frontmatter.section} status={frontmatter.status} />
This is easier to maintain than replacing the global title component for every page.
Accessibility Rules for Overrides
When you override built-in UI, you take responsibility for accessibility.
- Keep meaningful links as real
<a>elements. - Keep buttons as real
<button>elements when they perform actions. - Do not remove visible focus styles.
- Keep screen-reader text when replacing logos or titles.
- Use semantic HTML where possible.
- Test keyboard navigation.
Starlight’s default UI is designed with documentation usability in mind. Overrides should preserve or improve that usability.
Upgrade Safety
Component overrides are powerful, but they can be more fragile during upgrades than configuration or CSS.
Best practices:
- Keep overrides small.
- Add comments explaining why each override exists.
- Check the Starlight changelog before upgrading.
- Compare your override with the latest default implementation.
- Prefer wrapping or extending over full replacement when possible.
- Test navigation, search, mobile layout, and keyboard behavior after upgrades.
Common Mistakes
Overriding too soon
If CSS or configuration can solve the problem, use that first.
Copying old component code
Starlight changes over time. If you copy an old default component from a blog post or older project, it may not match your installed version.
Breaking mobile navigation
Header, sidebar, and search overrides can affect small screens. Always test on mobile widths.
Ignoring accessibility
Replacing built-in components can accidentally remove labels, focus behavior, or semantic HTML.
Putting content components in the overrides folder
Reusable content blocks belong in src/components/. Files that replace Starlight internals belong in src/overrides/.
Troubleshooting
The override does not appear
Check that the component name is correct and that the path in astro.config.mjs points to the right file.
The site fails to build
Check imports, component syntax, and whether you used props that are not available to that component.
The override works but styling is wrong
Check whether your CSS file is registered in customCss. Also check whether scoped component styles are taking precedence.
The page layout breaks on mobile
Use browser dev tools to test mobile widths. Built-in Starlight layout components often include responsive behavior you may need to preserve.
Search or navigation behaves strangely
If you overrode search, sidebar, or page navigation components, compare your replacement with the current Starlight default implementation.
Practice Exercise: Safe Customization
Before using overrides, practice with configuration and CSS.
- Create
src/styles/custom.css. - Register it with
customCss. - Add a logo through Starlight config.
- Create a splash homepage with
template: splash. - Create a custom MDX component for a lesson objective box.
This gives you a customized site without replacing Starlight internals.
Practice Exercise: First Override
After you are comfortable with safe customization, try a small override.
- Create
src/overrides/SiteTitle.astro. - Add simple custom markup for your site title.
- Register the override in
astro.config.mjs. - Run
npm run dev. - Test desktop and mobile layouts.
- Run
npm run build.
Start small. Do not begin by replacing the whole sidebar or page layout.
Full Example Configuration
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
site: 'https://example.com',
integrations: [
starlight({
title: 'World Bible and Lessons',
logo: {
light: './src/assets/light-logo.svg',
dark: './src/assets/dark-logo.svg',
},
customCss: ['./src/styles/custom.css'],
components: {
SiteTitle: './src/overrides/SiteTitle.astro',
},
sidebar: [
{
label: 'Start Here',
items: [
{ label: 'Home', slug: '' },
{ label: 'Getting Started', slug: 'getting-started' },
],
},
{
label: 'Lessons',
autogenerate: { directory: 'lessons' },
},
{
label: 'World Bible',
autogenerate: { directory: 'world' },
},
],
}),
],
});
Decision Guide
| Question | Action |
|---|---|
| Can this be done with frontmatter? | Use frontmatter. |
| Is this an official Starlight option? | Use astro.config.mjs. |
| Is this only visual styling? | Use custom CSS. |
| Is this reusable content inside a page? | Create a component in src/components/. |
| Do you need to change Starlight’s built-in markup or behavior? | Use a component override. |
Cheat Sheet
| Task | Where to Do It |
|---|---|
| Change site title | astro.config.mjs |
| Add logo | astro.config.mjs and src/assets/ |
| Add custom colors | src/styles/custom.css |
| Create a reusable content box | src/components/ |
| Use a custom component in a doc page | .mdx file |
| Replace built-in Starlight UI | components override config |
| Store override files | src/overrides/ |
What to Learn Next
- Starlight CSS and theme variables
- Astro component props and slots
- MDX component usage
- Starlight override reference
- Content collections and schemas
- Custom landing pages in Starlight
- Testing Starlight builds before deployment