systhema.config reference
Every configuration key with type, default and the page that explains it, and a full example.
On this page
Every key systhema.config.{ts,js,json} accepts. Where the file lives and how it is loaded is on Configuration.
| Option | Type | Default | Description |
|---|---|---|---|
blocks.accordion | | boolean | { enabled?: boolean closedIcon?: string | false openedIcon?: string | false openRotate?: number | false } | ||
blocks.applicationLayout | boolean | ||
blocks.article | boolean | ||
blocks.avatar | boolean | ||
blocks.button | | boolean | { enabled?: boolean icon?: string } | ||
blocks.card | boolean | ||
blocks.carousel | | boolean | { enabled?: boolean wrapperPrevIcon?: string wrapperNextIcon?: string bottomPrevIcon?: string bottomNextIcon?: string } | ||
blocks.chip | boolean | ||
blocks.columns | | boolean | { enabled?: boolean count?: number } | ||
blocks.container | boolean | ||
blocks.cookieConsent | boolean | ||
blocks.feature | boolean | ||
blocks.figure | boolean | ||
blocks.footer | boolean | ||
blocks.form | | boolean | { enabled?: boolean selectIcon?: string checkboxIcon?: string } | ||
blocks.gallery | | boolean | { enabled?: boolean prevIcon?: string nextIcon?: string } | ||
blocks.gap | boolean | ||
blocks.grid | | boolean | { enabled?: boolean paddingCols?: number } | ||
blocks.header | | boolean | { enabled?: boolean subNavigationIcon?: string menuIcon?: | { type: 'animated' } | { type: 'static' openIcon?: string closeIcon?: string } } | ||
blocks.hero | boolean | ||
blocks.icon | boolean | ||
blocks.layout | boolean | ||
blocks.link | boolean | ||
blocks.list | | boolean | { enabled?: boolean checkedIcon?: string uncheckedIcon?: string } | ||
blocks.media | | boolean | { enabled?: boolean overlayIcon?: string } | ||
blocks.posts | boolean | Posts-module presentation CSS (cards, highlight, meta, listing, archive filter, share buttons). | |
blocks.quote | | boolean | { enabled?: boolean icon?: string } | ||
blocks.richtext | boolean | ||
blocks.rootVariables | boolean | ||
blocks.section | boolean | ||
blocks.separator | boolean | ||
blocks.stack | boolean | ||
blocks.swiper | boolean | ||
blocks.typography | boolean | ||
blocks.variablesUtilities | boolean | ||
blocks | { rootVariables?: boolean variablesUtilities?: boolean applicationLayout?: boolean swiper?: boolean grid?: | boolean | { enabled?: boolean paddingCols?: number } gap?: boolean typography?: boolean link?: boolean layout?: boolean container?: boolean header?: | boolean | { enabled?: boolean subNavigationIcon?: string menuIcon?: | { type: 'animated' } | { type: 'static' openIcon?: string closeIcon?: string } } footer?: boolean article?: boolean hero?: boolean section?: boolean columns?: | boolean | { enabled?: boolean count?: number } feature?: boolean stack?: boolean gallery?: | boolean | { enabled?: boolean prevIcon?: string nextIcon?: string } figure?: boolean richtext?: boolean icon?: boolean list?: | boolean | { enabled?: boolean checkedIcon?: string uncheckedIcon?: string } media?: | boolean | { enabled?: boolean overlayIcon?: string } carousel?: | boolean | { enabled?: boolean wrapperPrevIcon?: string wrapperNextIcon?: string bottomPrevIcon?: string bottomNextIcon?: string } avatar?: boolean button?: | boolean | { enabled?: boolean icon?: string } chip?: boolean card?: boolean accordion?: | boolean | { enabled?: boolean closedIcon?: string | false openedIcon?: string | false openRotate?: number | false } quote?: | boolean | { enabled?: boolean icon?: string } separator?: boolean form?: | boolean | { enabled?: boolean selectIcon?: string checkboxIcon?: string } /** * Posts-module presentation CSS (cards, highlight, meta, listing, archive * filter, share buttons). Enable on projects that use the gated PayloadCMS * Posts module so its components are styled. Default on. */ posts?: boolean cookieConsent?: boolean } | ||
cookieConsent.categories | Partial<Record<SysthemaCookieCategoryId, SysthemaCookieCategoryConfig>> | ||
cookieConsent.cookie | { name?: string; expiresAfterDays?: number } | ||
cookieConsent.cookies | SysthemaCookieEntry[] | ||
cookieConsent.defaultLanguage | string | ||
cookieConsent.enabled | boolean | Master switch. | |
cookieConsent.guiOptions | any | Pass-through to vanilla-cookieconsent's guiOptions. | |
cookieConsent.hideFromBots | boolean | Pass-through to vanilla-cookieconsent's hideFromBots, which defaults to true and makes its run() short-circuit — no banner DOM, no error — whenever navigator.webdriver is set or the user agent matches its /bot|crawl|spider|slurp|teoma/i pattern. | |
cookieConsent.policyLinks | Array<{ /** Display label (e.g. `'Privacy Policy'`). Required. */ label: string /** Destination URL (already resolved — Payload reference resolution happens server-side). */ url: string /** Open in new tab with `rel="noopener"`. Default: `false`. */ newTab?: boolean }> | Links shown in the consent modal footer (e.g. | |
cookieConsent.reopenSelector | string | false | Selector that opens the preferences modal on click. | |
cookieConsent.scanner | { include?: string[] exclude?: string[] /** Override the bundled OCDB. URL or local path. */ databaseUrl?: string } | ||
cookieConsent.theme | string | Override the banner's color theme independently from the page. | |
cookieConsent.translations | Record<string, SysthemaCookieConsentTranslation> | ||
cookieConsent | SysthemaCookieConsentConfig | ||
customTokens.colorPrimitives | Record<string, unknown> | ||
customTokens.colorSystem | Record<string, unknown> | ||
customTokens.font | Record<string, unknown> | ||
customTokens.responsiveSizing | Record<string, unknown> | ||
customTokens.textStyles | Record<string, unknown> | Override existing composites or add .text-<kebab-path> typography styles. | |
customTokens | { font?: Record<string, unknown> responsiveSizing?: Record<string, unknown> colorPrimitives?: Record<string, unknown> colorSystem?: Record<string, unknown> /** Override existing composites or add `.text-<kebab-path>` typography styles. */ textStyles?: Record<string, unknown> } | ||
locales.default | string | ||
locales.fallback | boolean | ||
locales.missing | Readonly<Record<string, 'notFound' | 'fallback' | 'redirect'>> | Non-default locales with an EXPLICIT missing-translation override (including an explicit 'notFound'). | |
locales.routing | Readonly<{ localePrefix: 'always' | 'as-needed' localeDetection: boolean domains?: Readonly<Record<string, string>> /** * Sparse public-URL path-segment overrides — only locales whose * `subfolder` differs from their own code. Absent locale key = its code. * See {@link getSysthemaLocaleMissingBehavior} sibling helpers in * `locales.ts` for how this is applied to public output only (never to * `getSysthemaInternalLocalePathname`). */ subfolders?: Readonly<Record<string, string>> }> | ||
locales.rtl | readonly string[] | ||
locales.supported | readonly string[] | ||
locales | SysthemaLocales | Optional frontend locale contract. | |
manifest | any | ||
messages.catalogs | Readonly<Record<string, Readonly<Record<string, unknown>>>> | ||
messages.fallback | 'en' | Explicitly use the shipped English catalog for unregistered locales. | |
messages | SysthemaFrontendMessages | Frontend UI message catalogs, read from config at render time (no generated seam). | |
optimization.mergeThemeDuplicates | boolean | ||
optimization.obfuscateClasses | boolean | SysthemaObfuscationStyle | Class-name obfuscation. | |
optimization.obfuscateVariables | boolean | SysthemaObfuscationStyle | CSS variable-name obfuscation. | |
optimization.pruneUnchangedBreakpoints | boolean | ||
optimization.variableReferencesResolution | boolean | ||
optimization | boolean | SysthemaOptimizationConfig | ||
packages.payload | | boolean | { enabled?: boolean localization?: { /** * `'legacy'` (default) or `'all'`. Switching to `'all'` on a project that * holds content is a schema change and needs a back-fill migration first — * run `pnpm payload systhema-localization-report` to see what would move. * Full procedure: `node_modules/@systhemaui/payload/docs/localization-policy.md` * (https://docs.systhema.app/payload/localization/field-policy). */ policy?: 'legacy' | 'all' /** Field paths to keep shared. */ shared?: readonly string[] /** Array/blocks paths whose rows stay shared while their leaves localize. */ sharedRows?: readonly string[] /** Field paths to localize that the policy does not reach on its own. */ localized?: readonly string[] } } | true enables the Payload integration. | |
packages.react | | boolean | { enabled?: boolean animationClasses?: string transitionClasses?: string } | ||
packages | { react?: | boolean | { enabled?: boolean animationClasses?: string transitionClasses?: string } /** * `true` enables the Payload integration. The object form additionally * carries project-level Payload settings that belong next to the locale * contract rather than in `payload.config.ts` — today, the content * localization field policy. * * Core deliberately keeps `localization` untyped beyond its shape: * `@systhemaui/payload` owns the field-path vocabulary, and core must not * grow a dependency on Payload's schema types. */ payload?: | boolean | { enabled?: boolean localization?: { /** * `'legacy'` (default) or `'all'`. Switching to `'all'` on a project that * holds content is a schema change and needs a back-fill migration first — * run `pnpm payload systhema-localization-report` to see what would move. * Full procedure: `node_modules/@systhemaui/payload/docs/localization-policy.md` * (https://docs.systhema.app/payload/localization/field-policy). */ policy?: 'legacy' | 'all' /** Field paths to keep shared. */ shared?: readonly string[] /** Array/blocks paths whose rows stay shared while their leaves localize. */ sharedRows?: readonly string[] /** Field paths to localize that the policy does not reach on its own. */ localized?: readonly string[] } } } | ||
parallax.scale | number | ||
parallax.translateRangeBig | { from: number; to: number } | ||
parallax.translateRange | { from: number; to: number } | ||
parallax | { translateRange?: { from: number; to: number } translateRangeBig?: { from: number; to: number } scale?: number } | ||
spacing.exclude | string | string[] | false | ['feature.mediaMinHeight'] | Property paths/patterns to exclude from spacing transformation. |
spacing.function | string | "--spacing(%value% / 4)" | Template string for spacing value transformation. |
spacing.include | string | string[] | false | ['grid', 'gap', 'container', 'section', 'article', 'feature'] | Paths/patterns to transform within each screen size object in responsiveSizing. |
spacing.swap | boolean | false | When true, stores only the raw numeric value in :root variables. |
spacing | SpacingRule | SpacingRule[] | Configuration for spacing value transformation. |
manifestLink to this section
Imports your design-token manifest. The manifest references the token files Systhema should process.
import manifest from './tokens/manifest.json'
const config: SysthemaConfig = { manifest }In a JSON config file, use a path string:
{ "manifest": "./tokens/manifest.json" }If manifest is omitted, Systhema falls back to the built-in default tokens shipped in @systhemaui/core. What the manifest contains is described on Token collections.
spacingLink to this section
Controls how spacing values are transformed into CSS: a single SpacingRule or an array of them (function, include, exclude, swap). See Spacing rules.
blocksLink to this section
Toggles and configures the component CSS families. See Component CSS blocks.
parallaxLink to this section
Configures the parallax ranges (translateRange, translateRangeBig, scale). See Parallax.
customTokensLink to this section
Overrides or extends tokens without editing the JSON files. See Custom tokens.
packagesLink to this section
Enable framework-specific behaviour (mostly: emit safelists for that framework's components).
const config: SysthemaConfig = {
packages: {
react: {
enabled: true,
animationClasses: 'fade-in slide-up',
transitionClasses: 'transition-all duration-300',
},
payload: true,
},
}A boolean shorthand (react: true) is also supported.
payload also takes an object form carrying project-level Payload settings that belong next to the locale contract rather than in payload.config.ts — today, the content localization field policy:
const config: SysthemaConfig = {
packages: {
payload: {
enabled: true,
localization: { policy: 'all', shared: ['pages.default.hero.aspectRatio'] },
},
},
}Core keeps localization deliberately shallow — @systhemaui/payload owns the field-path vocabulary, and core must not grow a dependency on Payload's schema types. See the content localization field policy. This is NOT part of the locales contract on purpose: that object is inlined into the browser bundle as the build-time SYSTHEMA_LOCALES constant, so a field-path list on it would ship the project's schema shape to every visitor.
optimizationLink to this section
Production-only CSS passes and obfuscation. See Production CSS optimization.
cookieConsentLink to this section
The cookie consent banner. See Consent configuration.
localesLink to this section
Frontend locales, defined with defineSysthemaLocales(). See Frontend locales.
messagesLink to this section
Frontend UI catalogs (catalogs, fallback). See Messages and catalogs.
Full exampleLink to this section
import type { SysthemaConfig } from '@systhemaui/core'
import manifest from './tokens/manifest.json'
const config: SysthemaConfig = {
manifest,
spacing: {
function: '--spacing(%value% / 4)',
include: ['grid', 'gap', 'container', 'section'],
exclude: ['feature.mediaMinHeight'],
},
blocks: {
header: {
enabled: true,
subNavigationIcon: 'chevron-down',
menuIcon: { type: 'animated' },
},
columns: { enabled: true, count: 6 },
gallery: {
enabled: true,
prevIcon: 'arrow-left',
nextIcon: 'arrow-right',
},
},
parallax: {
translateRange: { from: -16, to: 16 },
translateRangeBig: { from: -32, to: 32 },
scale: 1.1666,
},
packages: {
react: {
enabled: true,
animationClasses: 'fade-in slide-up',
transitionClasses: 'transition-all duration-300',
},
},
}
export default config