This reference covers the styling customization surfaces in the site configuration system. For site identity, contact info, branding, and structural config, see Site Configuration (DOC-00002). For feature toggles (theme mode, analytics, lightbox), see Site Feature Configuration (DOC-00090).
Who this is for
- Implementors rebranding a site — changing fonts, colors, spacing, and fluid scales
- Developers understanding the core/site style override model
Typography & Font Overrides
Font customization is a site-level concern. The system separates font assets, token mapping, and element usage so implementors can change type without modifying core files.
Font Configuration
Font loading is managed by the Astro Fonts API. Core provides a default font trio and types in src/core/config/fonts.config.ts; sites customize by editing src/site/config/fonts.config.ts, which imports the core defaults and can replace them. The API handles @font-face generation, metric-adjusted fallback synthesis, and preload injection at build time.
| Purpose | Path | Notes |
|---|---|---|
| Font defaults and types | src/core/config/fonts.config.ts | Core-owned — DEFAULT_SITE_FONTS and FontEntry type. |
| Font configuration | src/site/config/fonts.config.ts | Site-owned — imports core defaults; replace with a custom FontEntry[] to customize. |
| Candidate/reference library | src/core/assets/font-library/ | Local font library for evaluation. Not used in production. |
| Default element-level usage | src/core/styles/base.css | Core baseline assignments for body, headings, code, and pre. |
| Site element-level overrides | src/site/styles/base.css | Site-specific element overrides loaded after core base styles. |
Change Fonts Workflow
- Edit
src/site/config/fonts.config.ts— change font names, weights, and providers. - Override primitive font-family tokens in
src/site/styles/primitives.cssif thecssVariablenames change. - Optionally remap semantic roles in
src/site/styles/semantic.cssif body/heading/prose/code roles should differ. - If needed, override element-level assignments in
src/site/styles/base.css.
Step 1: Edit Font Configuration in src/site/config/fonts.config.ts
The default site config imports and re-exports the core defaults. To customize, replace DEFAULT_SITE_FONTS with your own FontEntry[] array:
import { type FontEntry } from "../../core/config/fonts.config";
import { fontProviders } from "astro/config";
export const siteFonts: FontEntry[] = [
{
name: "Inter",
cssVariable: "--font-sans",
provider: fontProviders.google(),
weights: ["100 900"],
styles: ["normal"],
subsets: ["latin"],
display: "swap",
fallbacks: ["ui-sans-serif", "system-ui", "sans-serif"],
},
];
The Google Fonts provider downloads font files at build time and self-hosts them. No runtime CDN dependency. For offline or restricted builds, a commented-out local provider example is included in the default site config.
Step 2: (Optional) Override Primitive Tokens in src/site/styles/primitives.css
The default config uses --font-sans, --font-serif, and --font-mono as CSS variable names, which core primitives.css references. If you change the cssVariable names in fonts.config.ts, update the primitive tokens accordingly:
:root {
--pt-font-family-sans: var(--font-sans);
--pt-font-family-serif: var(--font-serif);
--pt-font-family-mono: var(--font-mono);
}
Step 3: (Optional) Remap Semantic Font Roles in src/site/styles/semantic.css
:root {
--st-font-family-body: var(--pt-font-family-sans);
--st-font-family-heading: var(--pt-font-family-serif);
--st-font-family-prose: var(--pt-font-family-serif);
--st-font-family-code: var(--pt-font-family-mono);
}
Use semantic remapping when role intent changes (for example, serif headings with sans body).
Step 4: Override Element Usage in src/site/styles/base.css (Optional)
src/core/styles/base.css defines default element bindings:
bodyuses--st-font-family-bodyh1–h6use--st-font-family-headingcodeandpreuse--st-font-family-code
If a site needs element-specific deviations, override those selectors in src/site/styles/base.css:
h1,
h2,
h3 {
letter-spacing: -0.02em;
}
Because src/site/styles/base.css is imported after src/core/styles/base.css, site rules win by cascade.
Fluid Token Overrides
Fluid spacing and typography tokens (--pt-space-*, --pt-text-*) are generated at build time from config files rather than hand-written CSS. To override the fluid scale for a site, edit src/site/config/fluid-tokens.config.ts instead of CSS files.
Config Structure
// src/site/config/fluid-tokens.config.ts (SITE-OWNED)
import type { FluidTokensSiteConfig } from "@core/config/fluid-tokens.config";
export default {
// Override viewport interpolation range (optional)
// vwMin: 20, // 320px — smallest viewport
// vwMax: 90, // 1440px — largest viewport
// Override individual spacing steps (optional)
// spacing: [
// { name: "md", min: 1.25, max: 2 }, // 20px–32px (core default: 24px–30px)
// ],
// Override individual typography steps (optional)
// typography: [
// { name: "lg", min: 1.25, max: 1.75 }, // 20px–28px (core default: 20px–24px)
// ],
// Override custom fluid tokens (optional — prop must exist in core config)
// custom: [
// { prop: "size-logo-header-width", min: 2.5, max: 4 }, // 40px–64px
// ],
} satisfies FluidTokensSiteConfig;
Only include the entries you want to change. Omitted entries inherit core defaults from src/core/config/fluid-tokens.config.ts. Scale arrays are merged by name (spacing/typography) or prop (custom) — a site entry replaces the core entry with the same key.
Workflow
- Edit
src/site/config/fluid-tokens.config.tswith your overrides. - Run
npm run generate:tokens— this regenerates bothsrc/core/styles/fluid-tokens.cssandsrc/site/styles/fluid-tokens.css. - Commit the updated config and generated CSS files.
The validate pipeline includes generate:tokens:check which fails if the generated CSS is out of sync with config, preventing stale tokens from shipping.
For the full token inventory and formula details, see Design Tokens — Fluid Token Generation.
Overriding Core Styles
The styling system is designed for site-level overrides without editing core files. Core defaults live in src/core/styles/; site overrides live in src/site/styles/ and are imported later, so they take precedence.
Import Precedence
src/core/styles/global.css controls load order. Core layers load first, then matching site layers:
src/core/styles/fluid-tokens.css->src/site/styles/fluid-tokens.css(generated — do not edit)src/core/styles/primitives.css->src/site/styles/primitives.csssrc/core/styles/semantic.css->src/site/styles/semantic.csssrc/core/styles/light.css->src/site/styles/light.csssrc/core/styles/dark.css->src/site/styles/dark.csssrc/core/styles/base.css->src/site/styles/base.csssrc/core/styles/components.css->src/site/styles/components.csssrc/site/styles/starwind-bridge.css(optional Starwind activation surface)src/core/styles/bridge.css->src/site/styles/bridge.css
This pairing is the default override path for theme and component styling. src/site/styles/starwind-bridge.css is intentionally site-only in the global import chain: it stays empty unless a site opts in to Starwind by importing the core Starwind bridge there. Fluid token files are generated by scripts/generate-fluid-tokens.ts — edit the config files instead (see Fluid Token Overrides).
src/core/styles/global.css also defines Tailwind’s class-detection scope. Automatic repo-wide detection is disabled with source(none), and the file explicitly registers the repository’s src/ tree as the only Tailwind source root via @source "../..". This prevents vendored references, notes, and other non-app files outside src/ from contributing classes or asset URLs to the production CSS bundle.
What to Override Where
| If you need to change… | Override file | Typical examples |
|---|---|---|
| Fluid spacing, typography, or custom | src/site/config/fluid-tokens.config.ts | spacing step sizes, type scale, viewport bounds, custom fluid tokens |
Raw baseline token values (--pt-*) | src/site/styles/primitives.css | font stacks, layout caps, motion values, component sizes |
Semantic role mappings (--st-*) | src/site/styles/semantic.css | body/heading font role mapping, layout gap role assignments |
Light mode colors (--st-color-*) | src/site/styles/light.css | surfaces, text, action colors, borders in light mode |
Dark mode colors (--st-color-*) | src/site/styles/dark.css | dark-mode semantic color set |
| Element-level CSS rules | src/site/styles/base.css | heading letter-spacing, blockquote style, default link style |
| Shared component CSS hooks | src/site/styles/components.css | site overrides for documented component classes |
| Starwind bridge activation | src/site/styles/starwind-bridge.css | optional core Starwind bridge import, Starwind aliases and mappings |
| Tailwind utility registrations | src/site/styles/bridge.css | @theme / @theme inline mappings for site-owned utility names |
Override Rules
- Do not edit
src/core/styles/*for site customization. - Override only the tokens/selectors that differ from defaults.
- Keep color usage token-based (
--st-color-*) in components and base styles. - When changing semantic color contracts, update both
light.cssanddark.cssto preserve mode parity.
Example: Override a Core Base Style
/* src/site/styles/base.css */
a {
text-decoration-thickness: 2px;
}
Example: Override a Core Token
/* src/site/styles/primitives.css */
:root {
--pt-layout-container-max: 72rem;
}