Skip to content

DMWD Starlight Theme

Jack added the full design system stylesheet to a Starlight site, and the reset overrode the site chrome and dark mode. Jill installed the Starlight plugin, kept her site CSS, and got the same token system and controls that the DMWD Storybook uses.

Use this guide for an Astro documentation site that needs the DMWD token system. It does not import the React component bundle or its global reset.

Before you start

  • Astro: 7.x
  • Starlight: 0.41.x
  • Package: @dmwd-io/design-system
  • A Starlight integration already present in astro.config.mjs

The package declares Astro and Starlight as peer dependencies, so the site keeps one copy of each framework.

Add the plugin

Install the design system beside the existing Astro and Starlight dependencies.

Terminal window
# Add the DMWD theme package to the documentation site.
# Docs: https://starlight.astro.build/reference/plugins/
pnpm add @dmwd-io/design-system

Add dmwdStarlightTheme() to the Starlight plugins array. It prepends the reset-free DMWD token stylesheet and the Starlight skin, while preserving any site-specific customCss entries.

// Apply DMWD tokens and controls to a Starlight site.
// Docs: https://starlight.astro.build/reference/plugins/
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
import { dmwdStarlightTheme } from "@dmwd-io/design-system/starlight";
export default defineConfig({
integrations: [
starlight({
title: "Acme documentation", // The site title remains owned by the consumer.
plugins: [dmwdStarlightTheme()], // Installs the two DMWD Starlight overrides.
customCss: ["katex/dist/katex.min.css"], // Keeps site-specific styles after the skin.
}),
],
});

Build the documentation site once after adding the plugin. The page should retain the usual Starlight layout while its surfaces, type, spacing, radius, focus states, and colors resolve through DMWD tokens.

Use the three theme controls

The theme control replaces Starlight’s text mode selector with the same control model used by DMWD Storybook.

Light and dark mode

The leading button shows a moon in light mode and a sun in dark mode. Activating it stores an explicit light or dark choice in Starlight’s normal theme preference, while a first visit still follows the operating-system preference.

Accent color

The accent menu renders the DMWD accent swatches from the shared theme metadata. Choosing a swatch updates semantic tokens such as links, focus rings, and primary actions without changing component markup.

Neutral and palette surfaces

The surface menu switches between the neutral and palette surface styles used in Storybook. It changes only semantic surface tokens, so foreground text and status colors remain readable in both light and dark mode.

Keyboard and assistive technology

Each trigger is a labeled button with a visible focus ring and a minimum 44px target. Each popover uses native radio controls and supports arrow-key selection and Escape to close. It announces the selected accent or surface style without relying on color alone.

Keep the token boundary clean

The Starlight plugin loads @dmwd-io/design-system/tokens.css, not the full styles.css or core.css entries. The token entry deliberately omits Tailwind preflight, element resets, and React component utilities. Those rules would otherwise compete with Starlight’s global layout.

Use semantic variables in site additions so an accent, surface, or mode selection updates the addition too.

/* Extend a Starlight page with DMWD semantic tokens.
* Docs: https://starlight.astro.build/guides/css-and-tailwind/
*/
.release-note {
background: hsl(var(--card)); /* Responds to the selected surface style. */
border-color: hsl(var(--border)); /* Uses the shared neutral border token. */
color: hsl(var(--card-foreground)); /* Preserves text contrast across modes. */
}

Do not import @dmwd-io/design-system/styles.css or core.css into a Starlight site. Those files own application-level reset and utility behavior. The plugin owns the safe docs site boundary.

Preserve control ownership

dmwdStarlightTheme() owns Starlight’s ThemeProvider and ThemeSelect slots. It rejects a competing override for either slot. A partial override could leave the saved mode and the accent or surface controls out of sync.

Keep other Starlight component overrides and customCss entries as usual. Use CSS variables for visual changes, or propose a shared control behavior change in the design system when the interaction itself must change.

Verify a consumer site

First run the focused package checks in this repository. They exclude Storybook, so they prove the theme contract without spending time on the full component catalog.

Terminal window
# Verify theme source, contracts, package assets, and the real docs-site build.
# Docs: https://starlight.astro.build/guides/css-and-tailwind/
task theme:check

Then check the consuming Astro site with its normal command surface. Test a first visit with the operating-system preference set to each mode. Select one accent and each surface style, reload, and confirm that the choices persist.

Acceptance criteria

  • The first page renders readable content before JavaScript finishes.
  • The mode toggle is a moon in light mode and a sun in dark mode.
  • Accent and surface changes update semantic tokens without a page reload.
  • Keyboard users can open a menu, change a radio option, and close it with Escape.
  • Every control has a visible focus indicator and a 44px minimum target.
  • A consumer’s non-conflicting customCss entries still load.

Upgrade without losing preferences

Keep the package, Astro, and Starlight versions within their supported ranges, then run the focused check before release. The preference payload carries a version number. Invalid selections fall back to the default accent and surface style, so a removed or renamed option cannot leave the page unthemed.

Compatibility

  • Astro: 7.x
  • Starlight: 0.41.x
  • Color modes: Starlight light and dark values
  • Accent choices: the DMWD shared theme metadata
  • Surface choices: DMWD neutral and palette styles

If it goes wrong

Jack kept an old ThemeSelect override while adding the plugin, so the build stopped with a slot-conflict error. Jill removed the competing override, kept her unrelated site CSS, and the DMWD controls mounted once in every responsive header.

The page loses Starlight styling

Remove any import of the full DMWD styles.css or core.css entry. The plugin loads the compatible token and skin entries automatically.

The build reports a theme-slot conflict

Remove the consumer ThemeProvider or ThemeSelect override before installing dmwdStarlightTheme(). The plugin preserves non-conflicting Starlight overrides.

A color looks hard-coded

Replace the local color value with the semantic token for its purpose, such as --foreground, --muted-foreground, --card, --border, or --primary. A semantic token follows every supported accent, surface, and mode selection.

The useful ending

Jack learned that a documentation site needs a token boundary, not an application reset. Jill now has a Starlight theme that follows the same DMWD controls and semantic tokens as Storybook. It remains safe to reuse across Astro sites.