Skip to content

Fix: Starlight Not Working — Pages Not Rendering, Sidebar Wrong, or Custom Components Broken

FixDevs · (Updated: )

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 Found

Or the sidebar doesn’t match your file structure:

Sidebar shows files in alphabetical order instead of custom order

Or 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 .md and .mdx files 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.mjs overrides auto-generation, and typos in slugs cause missing entries.
  • Starlight has its own built-in componentsCard, Tabs, Aside etc. come from @astrojs/starlight/components. Using generic Astro components or importing from the wrong path causes rendering issues.
  • Frontmatter controls page metadatatitle is required. Missing it causes build errors. sidebar frontmatter 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-package
  1. Create a configuration file

    Create config.ts in your project root.

  2. Start the dev server

    npm run dev

File Tree

- src/ - components/ - **Header.astro** - Footer.astro - pages/ - index.astro - styles/ - global.css - package.json - astro.config.mjs

Badges

DefaultNoteTipCautionDanger


## 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.mdx

Production 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 build

Look 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 itemsautogenerate: { 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.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles