CtrlK
BlogDocsLog inGet started
Tessl Logo

pantheon-ai/astro-starlight

Skills for setting up and customizing Astro Starlight documentation sites, covering project setup, custom theming, and component overrides.

100

Quality

100%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

SKILL.mdskills/starlight-custom-component/

name:
starlight-custom-component
description:
Create and override Astro Starlight UI components. Use when replacing or extending built-in Starlight components (header, footer, sidebar, page title, etc.), adding custom UI alongside existing components, accessing page route data inside a component, or applying overrides conditionally on specific pages.

Starlight Custom Components

Starlight's built-in UI can be extended or replaced by registering your own Astro components. Use this when CSS is not enough or you need behavioral changes.

When to Use

  • Changing a Starlight UI element that CSS alone cannot address
  • Adding new UI alongside an existing Starlight element (e.g., a banner above the header)
  • Replacing a built-in component with different markup or behavior
  • Conditionally rendering different UI on specific pages

When Not to Use

  • Simple color or font changes — use starlight-theme instead
  • Adding documentation content (pages, sidebars) — use starlight-base instead

Mindset

Starlight's UI is a set of named slots. You swap slot implementations, not DOM nodes.

  1. Named slots, not selectors. You register a replacement .astro file for a named component slot in astro.config.mjs. No CSS selector is involved — you replace the entire component rendering.
  2. Wrap, don't replace. Import the default component and render it inside your override to add behavior without duplicating Starlight's markup. This keeps you compatible with future Starlight updates.
  3. Page data lives in Astro.locals, not props. All route metadata is available via Astro.locals.starlightRoute. See overrides-reference.md for all available properties.

Step-by-Step: Override a Component

Step 1 — Identify the slot name from the Overrides Reference. Common ones: Header, Footer, PageTitle, Sidebar, TableOfContents, Hero, Pagination. Use the Overrides Map to visually locate UI areas.

Step 2 — Create the component:

---
// src/components/CustomFooter.astro
---
<footer>
  <p>Built with Starlight</p>
</footer>

Step 3 — Register in astro.config.mjs:

starlight({
  components: {
    Footer: './src/components/CustomFooter.astro',
  },
})

Wrapping a Built-in Component

---
// src/components/CustomSocialIcons.astro
import Default from '@astrojs/starlight/components/SocialIcons.astro';
---
<a href="mailto:hello@example.com">Contact</a>
<Default><slot /></Default>

For layout components with named slots (PageFrame, TwoColumnContent), transfer them explicitly:

<Default>
  <slot />
  <slot name="right-sidebar" slot="right-sidebar" />
</Default>

Accessing Page Data

---
const { title, description } = Astro.locals.starlightRoute.entry.data;
const isHomepage = Astro.locals.starlightRoute.id === '';
---

See overrides-reference.md for the full starlightRoute property table.

Anti-Patterns

NEVER register a component path with a leading slash

WHY: Paths in components: {} are relative to the project root. Consequence: Build error — component not found.

BAD: Footer: '/src/components/CustomFooter.astro' GOOD: Footer: './src/components/CustomFooter.astro'

NEVER omit <slot /> when wrapping a built-in component

WHY: Without <slot />, child content is silently discarded.

BAD: <Default /> (no slot) GOOD: <Default><slot /></Default>

Consequence: Sidebar links and other nested content disappear.

NEVER access page data via Astro.props in override components

WHY: Override components do not receive page data as props — only via Astro.locals.

BAD: const { title } = Astro.props; — always undefined GOOD: const { title } = Astro.locals.starlightRoute.entry.data;

Consequence: All page metadata is undefined.

NEVER rely on file name to determine which slot is overridden

WHY: Only the key in components: {} determines the slot, not the file name.

BAD: Naming a file Footer.astro without registering it in config. GOOD: Footer: './src/components/MyFooter.astro' in config.

Consequence: Default component renders unchanged.

NEVER forget to transfer named slots on layout components

WHY: PageFrame and TwoColumnContent expose named slots. Omitting them silently drops content. Consequence: Right sidebar disappears from all pages.

BAD: Wrap with only <Default><slot /></Default>

GOOD:

<Default>
  <slot />
  <slot name="right-sidebar" slot="right-sidebar" />
</Default>

NEVER import component internals not listed in the Overrides Reference

WHY: Only listed components are stable public API. Others may change without notice. Consequence: Imports break on minor version bumps.

BAD: Import an internal component not in the official reference. GOOD: Override only components from the official list.

References

skills

tile.json