Skip to content

Theming

Theming is treated as a system concern, not a per-component decision.

The goal is simple:

  • consistent UI across light and dark mode
  • minimal one-off styling
  • predictable token usage that scales

This site supports two themes:

  • Light mode (default)
  • Dark mode (opt-in)

Theme values are applied through CSS variables so components don’t need to “know” which theme is active.

In practice, theme switching updates semantic tokens like:

  • --background
  • --foreground
  • --primary
  • --border

…and the UI updates automatically.

Components should use semantic tokens, not raw palette values.

Semantic tokens represent intent:

  • “primary action”
  • “background surface”
  • “muted text”
  • “border color”

That keeps the system flexible. If the palette changes later, the component doesn’t.

Prefer this:

background: var(--background);
color: var(--foreground);
border-color: var(--border);

Avoid this:

background: var(--color-french-blue-950);
color: var(--color-french-blue-50);

Starlight has its own theme tokens (—sl-*) for docs styling.

This site maps the portfolio’s semantic tokens into Starlight so the docs feel like part of the same system.

That means:

  • portfolio UI tokens stay consistent
  • docs UI inherits the same design language
  • the docs don’t drift into a separate “mini theme”

Notes

Theming scales when:

  • palette tokens define the raw color system
  • semantic tokens define intent
  • components use semantic tokens consistently
  • docs inherit the same foundation instead of reinventing it