Fix: Starlight Not Working — Pages Not Rendering, Sidebar Wrong, or Custom Components Broken
Part of: React & Frontend Errors
Quick Answer
How to fix Astro Starlight documentation site issues — configuration, sidebar ordering, custom components, overrides, i18n, search, and content collections.
The Problem
Starlight pages return 404:
GET /guides/getting-started → 404 Not FoundOr the sidebar doesn’t match your file structure:
Sidebar shows files in alphabetical order instead of custom orderOr custom components don’t render in MDX:
import { Card } from '@astrojs/starlight/components';
<Card title="Hello">Content</Card>
<!-- Renders as plain text -->Why This Happens
Starlight is Astro’s official documentation theme. It builds on Astro’s content collections:
- Docs must be in
src/content/docs/— Starlight reads.mdand.mdxfiles from this specific directory. Files elsewhere aren’t recognized. - Sidebar is auto-generated or manually configured — by default, Starlight creates sidebar entries from the file structure. Manual sidebar config in
astro.config.mjsoverrides auto-generation, and typos in slugs cause missing entries. - Starlight has its own built-in components —
Card,Tabs,Asideetc. come from@astrojs/starlight/components. Using generic Astro components or importing from the wrong path causes rendering issues. - Frontmatter controls page metadata —
titleis required. Missing it causes build errors.sidebarfrontmatter overrides the global sidebar config for that page.
Most Starlight failures trace back to the tight coupling between Astro’s content collections and Starlight’s routing. Starlight registers docs as a content collection automatically and walks files under src/content/docs/ to build routes, the sidebar tree, and the search index in a single pass. If astro:content fails to parse a file — usually because of an invalid frontmatter field or a missing title — the build either crashes or skips the file entirely, depending on the Astro version. A skipped file produces a 404 with no warning in the build log, which is the failure mode that bites teams in production.
The second class of failure is configuration drift between astro.config.mjs and the actual file tree. When you write slug: 'guides/introduction' in your sidebar config, Starlight does not fuzzy-match — it expects an exact file at src/content/docs/guides/introduction.md or .mdx. Rename the file to intro.mdx without updating the config and the build still succeeds, but the sidebar link 404s and the rest of the sidebar shifts around it.
Treating the docs site as production infrastructure is critical. A broken Starlight build on Vercel or Netlify often takes down your entire developer portal, and downstream effects include support tickets, broken onboarding for new customers, and embarrassing 404s from outbound links shared on social media. Wire your Astro build into CI, gate every PR behind a preview deploy, and add an uptime check that asserts a known-good URL like /guides/installation/ returns 200.
Fix 1: Setup Starlight
npm create astro@latest -- --template starlight
# Or add to existing Astro project:
npx astro add starlight// astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
logo: {
src: './src/assets/logo.svg',
alt: 'My Project',
},
// Social links
social: {
github: 'https://github.com/user/repo',
discord: 'https://discord.gg/xxx',
},
// Sidebar configuration
sidebar: [
{
label: 'Getting Started',
items: [
{ label: 'Introduction', slug: 'guides/introduction' },
{ label: 'Installation', slug: 'guides/installation' },
{ label: 'Quick Start', slug: 'guides/quick-start' },
],
},
{
label: 'Core Concepts',
autogenerate: { directory: 'concepts' },
// Auto-generates from src/content/docs/concepts/
},
{
label: 'API Reference',
collapsed: true, // Collapsed by default
autogenerate: { directory: 'api' },
},
{
label: 'Resources',
items: [
{ label: 'GitHub', link: 'https://github.com/user/repo', attrs: { target: '_blank' } },
{ label: 'Changelog', slug: 'changelog' },
],
},
],
// Custom CSS
customCss: ['./src/styles/custom.css'],
// Default language
defaultLocale: 'en',
// Search
pagefind: true, // Built-in search (default)
// Edit link
editLink: {
baseUrl: 'https://github.com/user/repo/edit/main/',
},
// Table of contents
tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 3 },
// Head tags
head: [
{ tag: 'meta', attrs: { property: 'og:type', content: 'website' } },
],
}),
],
});Fix 2: Content Structure and Frontmatter
src/content/docs/
├── index.mdx # /
├── guides/
│ ├── introduction.mdx # /guides/introduction
│ ├── installation.mdx # /guides/installation
│ └── quick-start.mdx # /guides/quick-start
├── concepts/
│ ├── architecture.mdx # /concepts/architecture
│ └── configuration.mdx # /concepts/configuration
├── api/
│ ├── client.mdx # /api/client
│ └── server.mdx # /api/server
└── changelog.mdx # /changelog---
title: Installation Guide
description: How to install and set up the project
sidebar:
order: 2 # Manual ordering within auto-generated groups
badge:
text: New
variant: tip # note | tip | caution | danger
# label: Custom Label # Override sidebar label
tableOfContents:
minHeadingLevel: 2
maxHeadingLevel: 4
---
# Installation Guide
Follow these steps to install the project.
## Prerequisites
You need Node.js 18 or higher.
## Install
```bash
npm install my-package
```mdx
---
title: Advanced Configuration
description: Deep dive into configuration options
sidebar:
order: 5
badge: Advanced
---
Content here...Fix 3: Built-In Components
---
title: Component Examples
---
import { Card, CardGrid, Aside, Tabs, TabItem, LinkCard, Steps, Badge, Icon, FileTree } from '@astrojs/starlight/components';
## Cards
<CardGrid>
<Card title="Quick Start" icon="rocket">
Get up and running in 5 minutes.
</Card>
<Card title="API Reference" icon="document">
Complete API documentation.
</Card>
<Card title="Examples" icon="puzzle">
Real-world usage examples.
</Card>
</CardGrid>
<LinkCard title="View on GitHub" href="https://github.com/user/repo" description="Star us on GitHub!" />
## Asides (Callouts)
<Aside>This is a note.</Aside>
<Aside type="tip">This is a helpful tip!</Aside>
<Aside type="caution">Be careful with this.</Aside>
<Aside type="danger">This could break your app!</Aside>
## Tabs
<Tabs>
<TabItem label="npm">
```bash
npm install my-package
```
</TabItem>
<TabItem label="pnpm">
```bash
pnpm add my-package
```
</TabItem>
<TabItem label="yarn">
```bash
yarn add my-package
```
</TabItem>
</Tabs>
## Steps
<Steps>
1. Install the package
```bash
npm install my-packageCreate a configuration file
Create
config.tsin your project root.Start the dev server
npm run dev
File Tree
Badges
Default
## Fix 4: Custom Overrides
```typescript
// astro.config.mjs — override Starlight components
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
components: {
// Override the header
Header: './src/components/CustomHeader.astro',
// Override the footer
Footer: './src/components/CustomFooter.astro',
// Override the page sidebar
// Sidebar: './src/components/CustomSidebar.astro',
},
}),
],
});<!-- src/components/CustomHeader.astro -->
---
import Default from '@astrojs/starlight/components/Header.astro';
---
<!-- Extend the default header -->
<Default {...Astro.props}>
<div slot="after">
<a href="https://github.com/user/repo" class="github-badge">
⭐ Star on GitHub
</a>
</div>
</Default>
<style>
.github-badge {
background: #333;
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.8rem;
text-decoration: none;
}
</style>/* src/styles/custom.css — customize Starlight's CSS variables */
:root {
--sl-color-accent-low: #1e1b4b;
--sl-color-accent: #4f46e5;
--sl-color-accent-high: #c7d2fe;
--sl-color-white: #ffffff;
--sl-color-gray-1: #f8fafc;
--sl-color-gray-2: #e2e8f0;
--sl-color-gray-3: #94a3b8;
--sl-color-gray-4: #475569;
--sl-color-gray-5: #1e293b;
--sl-color-gray-6: #0f172a;
--sl-color-black: #020617;
--sl-font: 'Inter', sans-serif;
--sl-font-mono: 'Fira Code', monospace;
}
/* Custom sidebar width */
:root {
--sl-sidebar-width: 280px;
}
/* Style code blocks */
.sl-markdown-content pre {
border-radius: 8px;
border: 1px solid var(--sl-color-gray-5);
}Fix 5: Internationalization (i18n)
// astro.config.mjs — multi-language docs
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
defaultLocale: 'en',
locales: {
en: { label: 'English' },
ja: { label: '日本語', lang: 'ja' },
es: { label: 'Español', lang: 'es' },
},
sidebar: [
{
label: 'Guides',
translations: {
ja: 'ガイド',
es: 'Guías',
},
autogenerate: { directory: 'guides' },
},
],
}),
],
});src/content/docs/
├── en/
│ └── guides/
│ └── getting-started.mdx
├── ja/
│ └── guides/
│ └── getting-started.mdx
└── es/
└── guides/
└── getting-started.mdxProduction Incident: Astro Docs Build Fails on Vercel, Dev Portal Goes Dark
The classic Starlight outage looks like this: a contributor merges a PR that renames a file or tweaks frontmatter, the Vercel build fails on main, and the existing production deployment keeps serving traffic — until the next deploy of an unrelated change triggers a rebuild that also fails, at which point Vercel rolls forward to the failed build and the docs site disappears.
The blast radius is wider than you think. Marketing pages on the same subdomain may break, the search box vanishes, every external link to a specific /guides/... URL 404s, and your developer onboarding flow grinds to a halt because customers can’t find install instructions. If the docs live at a custom domain like docs.example.com, status page integrations may not detect the failure for hours.
Reproduce the failure locally against the exact commit:
git checkout <failing-sha>
npm ci
npm run buildLook for the Astro error type. AstroError: Could not find a config file means a missing astro.config.mjs. Content collection error means a frontmatter mismatch — Starlight requires title and rejects unknown fields by default. ENOENT errors during the build point at a slug: reference in astro.config.mjs whose target file no longer exists.
The fastest mitigation is to redeploy the last known-good build from the Vercel or Netlify dashboard while you fix main. Do not push fixes blindly under pressure — each Astro rebuild takes long enough that you’ll cause more downtime trying to fix in production than you would by rolling back.
Add a CI step that runs npm run build before merging, and a synthetic check that fetches your top three doc URLs every five minutes. The cost is negligible and it converts a multi-hour silent outage into a five-minute page.
Beyond uptime, audit the deploy hook. A common gotcha is that Vercel and Netlify auto-deploy on every push to main, but only show build failures in the dashboard. If nobody is watching the dashboard, a series of failed builds can pile up unnoticed while the production site happily serves the last successful artifact. Configure build-failure notifications to Slack or PagerDuty so the team sees red builds the moment they happen. Pair this with a weekly review of build success rates; trending failures often surface a deeper issue with a contributor workflow that needs an automated fix.
Fix 6: Plugins and Extensions
# Starlight plugins
npm install starlight-links-validator # Check for broken links
npm install starlight-blog # Add a blog// astro.config.mjs
import starlightLinksValidator from 'starlight-links-validator';
import starlightBlog from 'starlight-blog';
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
plugins: [
starlightLinksValidator(),
starlightBlog({
title: 'Blog',
authors: {
alice: { name: 'Alice', title: 'Lead Dev', picture: '/authors/alice.jpg' },
},
}),
],
}),
],
});Still Not Working?
Pages return 404 — docs must be in src/content/docs/. The URL path mirrors the file path: src/content/docs/guides/intro.mdx → /guides/intro. Check for typos in filenames and ensure the file has valid frontmatter with at least a title field.
Sidebar order is wrong — auto-generated sidebars sort alphabetically by default. Use sidebar.order in frontmatter to control ordering within a group. Lower numbers appear first. Or switch to manual sidebar config in astro.config.mjs.
Components import fails — Starlight components must be imported from @astrojs/starlight/components. Using import { Card } from 'astro' or other paths won’t work. Make sure the file is .mdx (not .md) to use imports.
Custom CSS doesn’t apply — add the CSS file path to customCss array in the Starlight config. CSS variables must use Starlight’s variable names (prefixed --sl-). Inspect the page to find the correct variable names.
Search returns “no results” for content that exists — Starlight uses Pagefind, which indexes the static build output, not the source files. Run npm run build and check that dist/pagefind/ exists. If the directory is missing, pagefind: true may be disabled by an override or by deploying only dist/client/. Make sure your host serves the entire dist/ directory.
Build fails with “Could not resolve content collection schema” — Starlight registers its own docs collection schema. If you add a custom src/content/config.ts that overrides it without extending Starlight’s schema, frontmatter validation breaks. Import docsSchema from @astrojs/starlight/schema and extend it with .extend() rather than replacing it.
Pages render but missing sidebar items — autogenerate: { directory: 'guides' } only includes files inside src/content/docs/guides/. Nested directories require nested entries or collapsed: true. Files without a title frontmatter are skipped silently. See Fix: Astro Content Collections Not Working for the underlying collection rules.
For related documentation issues, see Fix: Nextra Not Working, Fix: MDX Not Working, and Fix: Vercel Deployment Failed.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Astro Server Islands Not Working — server:defer, Fallback, Cookies, Caching, and Hydration
How to fix Astro 5 server islands — server:defer directive ignored, fallback slot missing, cookies/headers in deferred component, output config mismatch, dynamic island fetch URL, and caching the static shell.
Fix: MkDocs Not Working — Material Theme, Navigation, and Plugin Errors
How to fix MkDocs errors — Config value 'theme' must be a string or dict, mkdocstrings not generating API docs, navigation pages missing, mkdocs serve port already in use, GitHub Pages deploy failed, and broken links not detected.
Fix: Sphinx Not Working — Autodoc Import Errors, Theme Issues, and Cross-References
How to fix Sphinx errors — autodoc cannot import module, theme not found, intersphinx links broken, ReadTheDocs build failed, MyST markdown not rendering, and unknown directive in conf.py.
Fix: Astro DB Not Working — Tables Not Found, Queries Failing, or Seed Data Missing
How to fix Astro DB issues — schema definition, seed data, queries with drizzle, local development, remote database sync, and Astro Studio integration.