starlight-custom-component · git:20261002.e6369ee · 2026-10-02 · sha256 f43a9c1047a70acd
starlight-custom-component git:20261002.e6369eeA
Immutable. This exact content never changes and is served at /api/v1/blob/f43a9c1047a70acd.
---
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
## Philosophy
**Starlight's UI is a set of named slots. You swap slot implementations, not DOM nodes.**
- **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.
- **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.
- **Page data lives in `Astro.locals`, not props.** All route metadata is available via `Astro.locals.starlightRoute`. See [overrides-reference.md](./references/overrides-reference.md) for all available properties.
## Step-by-Step: Override a Component
**Step 1 — Identify the slot name** from the [Overrides Reference](https://starlight.astro.build/reference/overrides/). Common ones: `Header`, `Footer`, `PageTitle`, `Sidebar`, `TableOfContents`, `Hero`, `Pagination`. Use the [Overrides Map](https://starlight-overrides-map.netlify.app/) to visually locate UI areas.
**Step 2 — Create the component:**
```astro
---
// src/components/CustomFooter.astro
---
<footer>
<p>Built with Starlight</p>
</footer>
```
**Step 3 — Register in `astro.config.mjs`:**
```js
starlight({
components: {
Footer: './src/components/CustomFooter.astro',
},
})
```
## Wrapping a Built-in Component
```astro
---
// 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:
```astro
<Default>
<slot />
<slot name="right-sidebar" slot="right-sidebar" />
</Default>
```
## Accessing Page Data
```astro
---
const { title, description } = Astro.locals.starlightRoute.entry.data;
const isHomepage = Astro.locals.starlightRoute.id === '';
---
```
See [overrides-reference.md](./references/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. **Consequence:** Sidebar links and other nested content disappear.
**BAD:** `<Default />` (no slot)
**GOOD:** `<Default><slot /></Default>`
### NEVER access page data via `Astro.props` in override components
**WHY:** Override components do not receive page data as props, only via `Astro.locals`. **Consequence:** All page metadata is `undefined`.
**BAD:** `const { title } = Astro.props;` (always `undefined`)
**GOOD:** `const { title } = Astro.locals.starlightRoute.entry.data;`
### NEVER rely on file name to determine which slot is overridden
**WHY:** Only the key in `components: {}` determines the slot, not the file name. **Consequence:** Default component renders unchanged.
**BAD:** Naming a file `Footer.astro` without registering it in config.
**GOOD:** `Footer: './src/components/MyFooter.astro'` in config.
### 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:**
```astro
<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](https://starlight.astro.build/reference/overrides/).
### NEVER fully replace a component when wrapping the default would do
**WHY:** Wrapping keeps you compatible with future Starlight updates and avoids duplicating Starlight's markup. **Consequence:** Replaced markup drifts from upstream behaviour.
**BAD:** Copy the whole header markup to add one banner.
**GOOD:** Import the default component and render your banner before `<Default><slot /></Default>`.
### NEVER guess the slot name
**WHY:** The key in `components: {}` must be an exact named slot from the Overrides Reference. **Consequence:** An unknown key overrides nothing.
**BAD:** `components: { MyHeader: './src/components/Header.astro' }`
**GOOD:** Look up the slot (for example `Header`) in the Overrides Reference, then register it under that exact name.
### NEVER override a component when CSS alone is enough
**WHY:** Colour and font changes belong to `starlight-theme`; overrides add maintenance cost for no behavioural gain. **Consequence:** Needless coupling to Starlight's component structure.
**BAD:** Replace `Header` to change its background colour.
**GOOD:** Change the colour with CSS variables as described in `starlight-theme`.
### NEVER use this skill to add documentation pages or sidebars
**WHY:** Content and navigation are covered by `starlight-base`. **Consequence:** Content guidance is missed and the wrong patterns are applied.
**BAD:** Create a custom component just to list pages.
**GOOD:** Add pages and sidebar entries as described in `starlight-base`.
## References
| Topic | Reference | When to Use |
| --- | --- | --- |
| Overrides and route data | [Overrides Reference](./references/overrides-reference.md) | Looking up slot names and `starlightRoute` properties |
| Guide | [Overriding Components Guide](https://starlight.astro.build/guides/overriding-components/) | Learning the override flow |
| Route data | [Route Data Reference](https://starlight.astro.build/reference/route-data/) | Reading page data in a component |
| Visual map | [Starlight Overrides Map (interactive)](https://starlight-overrides-map.netlify.app/) | Locating the UI area to override |
| Astro slots | [Astro Components: Slots](https://docs.astro.build/en/basics/astro-components/#slots) | Understanding default and named slots |