Themes
PureStack generates theme CSS from palettes. Each skin supplies light and dark values for type, surfaces, borders, and semantic tones. Components read those shared values so a theme change stays consistent across the page.
See Semantic tone classes for visual examples of the roles generated from those palettes.
Start with the standard skin
Add this to siteConfig.json:
{
"style": {
"fileName": "site.css",
"href": "/assets/site.css",
"themes": ["light", "dark"],
"theme": { "skin": "standard" }
}
} The generator writes assets/site.css for light and assets/site.dark.css for dark. Its theme toggle uses the configured theme list and remembers a visitor's choice. Try the ThemeToggle example on this site.
Create a skin
Start from a standard color preset and override the values your design needs:
import { registerSkin, themeSkins } from '@purestack/ts-style'
import { merge } from '@purestack/ts-util'
registerSkin('my-site', {
create: () => {
const standard = themeSkins.standard.create(['green'])
return {
light: merge(standard.light, {
font: { size: { body: '1rem' } },
}),
dark: merge(standard.dark, {
font: { size: { body: '1rem' } },
}),
}
},
}) Import the file that registers your skin before the site build begins, then set "theme": { "skin": "my-site" } in the style config. A skin is a full light/dark pair; the preset gives related semantic colors a coherent starting point, and merge preserves values you do not override.
Extend styles with palette roles
Use semantic roles when a custom section needs color, so it follows both themes:
import { styleBuilder, themes } from '@purestack/ts-style'
themes.forEach((theme, palette) => {
styleBuilder.get(theme).select('.feature-note').css({
background: palette.semanticTone.info.surface.rest.background,
color: palette.semanticTone.info.surface.rest.text,
borderColor: palette.semanticTone.info.surface.rest.border,
})
}) Register such styles in your site runner before the build renders theme assets. For a real example, inspect the Studio skin and Studio styles.