Bolt CMS Docs
Sign in

Rendering Content

Design System

CSS custom properties, the color token reference, typography scale, and spacing conventions used across Bolt CMS sites.

CSS Variables

Bolt CMS defines its design as CSS custom properties (design tokens) holding complete color strings. Reference a token directly with var(--token) in any css="" attribute or <style> block — no rgb() wrapper needed. The tokens are injected once, globally, by the front controller, so every page reads the same values.

The palette is GitHub-inspired and ships in two modes. The light values live on :root; the dark values override them under html[data-theme="dark"]. The same var(--token) resolves to whichever mode is active, so it themes automatically.

:root {
    --background: #ffffff;   --card: #ffffff;
    --foreground: #1f2328;   --muted: #656d76;
    --border: #d0d7de;       --accent: #0969da;   /* links, active nav */
    --primary: #1f883d;      /* primary buttons (green) */
    --destructive: #cf222e;  --radius: 6px;
    /* …plus surface, text, and callout tokens — see the table below */
}

html[data-theme="dark"] {
    --background: #0d1117;   --card: #161b22;
    --foreground: #e6edf3;   --muted: #7d8590;
    --border: #30363d;       --accent: #2f81f7;
    --primary: #238636;      --destructive: #f85149;
}

Usage in css=""

Reference a token inside any css="" declaration directly with var() — no rgb() wrapper:

<div css="background: var(--background); color: var(--foreground);">
    <p css="color: var(--muted);">Muted text</p>
    <button css="background: var(--primary); color: #ffffff;">Action</button>
</div>

Because each token holds a complete color string, the full rgb() / rgba() forms are valid token values too — for example a token could be defined as --primary-tint: rgba(59,130,246,0.1) for a 10% primary tint (write the rgba() with no internal spaces so the css="" tokenizer keeps it intact). The --radius token is a plain length, so it also works directly: border-radius: var(--radius).

Light & dark mode

The active mode is the data-theme attribute on the <html> element — light or dark. A small inline script sets it before first paint from the visitor's saved choice (localStorage['bolt-theme']), falling back to the operating system's prefers-color-scheme, so there is no flash of the wrong theme. The toggle in the header flips it:

// flip the mode and remember it
boltToggleTheme();

Because every surface uses var(--token), switching data-theme re-resolves the whole page through the cascade — no stylesheet re-render is required.

Editing the palette

Administrators can tweak every token value — for both modes — from Appearance in the admin dashboard. Saved changes are stored as overrides and applied site-wide; Reset to defaults restores the GitHub values shown here.

Color Token Reference

The full token set. Color tokens carry a light and a dark value; --radius is shared across modes.

Token Role Light Dark
--backgroundPage background#ffffff#0d1117
--cardCard / panel surface#ffffff#161b22
--surface-subtleSubtle surface (table head, hover)#f6f8fa#161b22
--surface-insetInset surface (inline code)#eaeef2#21262d
--foregroundPrimary text#1f2328#e6edf3
--text-secondarySecondary / body text#3a4148#c9d1d9
--mutedMuted text, captions#656d76#7d8590
--text-faintFaint text, placeholders#818b98#6e7681
--borderDefault border#d0d7de#30363d
--border-strongStrong / hover border#afb8c1#444c56
--accentLinks, active nav, focus#0969da#2f81f7
--accent-hoverAccent hover#0860ca#388bfd
--primaryPrimary button (green)#1f883d#238636
--primary-foregroundText on primary#ffffff#ffffff
--destructiveDanger text / delete#cf222e#f85149
--info-fg / --info-bgInfo callout#0969da / #ddf4ff#2f81f7 / rgba(56,139,253,.12)
--success-fg / --success-bgSuccess callout#1a7f37 / #dafbe1#3fb950 / rgba(46,160,67,.15)
--warning-fg / --warning-bgWarning callout#9a6700 / #fff8c5#d29922 / rgba(187,128,9,.15)
--violet-fg / --violet-bgNote callout#8250df / #fbefff#a371f7 / rgba(163,113,247,.15)
--danger-bgDanger background#ffebe9rgba(248,81,73,.15)
--radiusCorner radius6px (shared)

Typography

Font

Bolt CMS uses Inter from Google Fonts as the primary typeface, loaded with weights 300-700 for body text and UI. Code blocks use JetBrains Mono.

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">

Type Scale

Each role below lists the css="" declaration that produces it. Sizes are in rem (1rem = 16px), and responsive jumps use breakpoint tokens.

Context css="" Size
Hero title font-size: 3rem md:4.5rem; font-weight: 700; letter-spacing: -0.025em; 3rem / 4.5rem
Section heading font-size: 1.875rem md:2.25rem; font-weight: 700; 1.875rem / 2.25rem
Card title font-size: 1.125rem; font-weight: 600; 1.125rem
Body text font-size: 1rem; 1rem
Meta/caption font-size: 0.875rem; color: var(--muted); 0.875rem
Eyebrow label font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 500; 0.75rem

Spacing Conventions

Consistent spacing creates visual rhythm across pages. Follow these standard patterns.

Container

<div css="max-width: 80rem; margin-left: auto; margin-right: auto; padding-left: 1rem sm:1.5rem lg:2rem; padding-right: 1rem sm:1.5rem lg:2rem;">
    <!-- Page content -->
</div>

Section Padding

Context css=""
Standard section padding-top: 3rem; padding-bottom: 3rem; to 5rem
Hero section padding-top: 6rem md:8rem; padding-bottom: 6rem md:8rem;
Tight section (FAQ, footer) padding-top: 2rem; padding-bottom: 2rem; to 3rem

Internal Spacing

  • Between heading and content: margin-top: 1rem to 1.5rem
  • Between heading and grid: margin-top: 3rem to 4rem
  • Card internal padding: padding: 1.5rem to 2rem
  • Grid gap: gap: 1.5rem to 2rem

Responsive Grid Patterns

Grids stack on mobile, expand to 2 columns on tablet, and 3 columns on desktop. Add the column counts as breakpoint tokens so the base layout is the single-column mobile case.

<!-- Standard 3-column feature grid -->
<div css="display: grid; gap: 2rem; grid-template-columns: repeat(1,minmax(0,1fr)) md:repeat(2,minmax(0,1fr)) lg:repeat(3,minmax(0,1fr));">
    <!-- Cards -->
</div>

<!-- 2-column comparison -->
<div css="display: grid; gap: 3rem; grid-template-columns: repeat(1,minmax(0,1fr)) md:repeat(2,minmax(0,1fr));">
    <!-- Columns -->
</div>

<!-- 4-column stats/metrics -->
<div css="display: grid; gap: 1.5rem; grid-template-columns: repeat(2,minmax(0,1fr)) md:repeat(4,minmax(0,1fr));">
    <!-- Stat cards -->
</div>
Paradigm CSS Component patterns