Building: full-width layout
The full-width layout keeps the left navigation sidebar but drops the right-hand table-of-contents column, letting the main content pane use all the remaining horizontal space. It’s a good fit for wide diagrams, tables, or reference pages where a floating TOC gets in the way.
See it live: /demos/full-width/.
Why TwoColumnContent
Section titled “Why TwoColumnContent”Looking at Starlight’s default Page composition, the right-hand column
comes from TwoColumnContent, not PageFrame:
PageFrame├─ Header (slot="header")├─ Sidebar (slot="sidebar", left nav)└─ TwoColumnContent ├─ PageSidebar (slot="right-sidebar", the TOC column) └─ <main> (page content)TwoColumnContent is the component responsible for laying out its two
children side by side, so it’s the one to override to remove that second
column.
The override
Section titled “The override”---import Default from '@astrojs/starlight/components/TwoColumnContent.astro';import { getLayout } from '../../layouts.config';
const { entry } = Astro.locals.starlightRoute;const layout = getLayout(entry.data.pageLayout);---
{layout?.wide ? ( <div class="main-pane main-pane--full"> <slot /> </div>) : ( <Default> <slot name="right-sidebar" slot="right-sidebar" /> <slot /> </Default>)}
<style> @layer starlight.core { .main-pane--full { isolation: isolate; width: 100%; } }</style>getLayout() looks up the active pageLayout value in a small registry
assembled from every installed @dagilleland/layout-* package —
Composing layout packages covers
that registry in full. For now, what matters is wide: it’s a flag three
different layout packages set (full-width, minimal, and dashboard),
all wanting the right column gone — the minimal layout
goes a step further and also removes the left sidebar.
Note that when layout?.wide is true, the right-sidebar slot content
Starlight passes in (the actual PageSidebar/table of contents) is simply
never rendered — it’s still computed upstream, just discarded here. That’s
fine for a demo site; on a larger project you’d weigh whether skipping the
computation entirely (further upstream) is worth the complexity.
The width cap this alone doesn’t remove
Section titled “The width cap this alone doesn’t remove”Widening TwoColumnContent’s main pane isn’t the whole story. Starlight
separately wraps page content in ContentPanel, which caps width at
--sl-content-width (45rem on this site, since a sidebar is always
configured) regardless of how wide its parent is — so without a second
override, this page’s content would still sit in a 45rem column with empty
space to its right where the TOC used to be.
This project also overrides ContentPanel, checking the same wide flag
as TwoColumnContent above, so full-width pages actually use the width
they reclaim. The dashboard layout tutorial
walks through that override in full — it’s introduced there because a
widget grid makes the cap’s effect obvious, but it applies here too.
Wiring it up
Section titled “Wiring it up”The dispatcher above is registered once in astro.config.mjs, alongside
the other overrides:
starlight({ components: { TwoColumnContent: './src/components/overrides/TwoColumnContent.astro', ContentPanel: './src/components/overrides/ContentPanel.astro', // ... },});full-width itself, though, lives in its own package —
packages/layout-full-width/ — since wide is the only thing it needs,
it’s the simplest of the four:
export const fullWidthMeta = { id: 'full-width', wide: true,} as const;And used from a page:
---title: Full-width layoutpageLayout: full-width---Every other page — including this one — has no pageLayout frontmatter,
so getLayout() returns undefined and both dispatchers fall straight
through to <Default>, rendering exactly as stock Starlight would.