Docs

This page isn't translated yet

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.

OptionTypeDefaultDescription
blocks.accordion| boolean | { enabled?: boolean closedIcon?: string | false openedIcon?: string | false openRotate?: number | false }
blocks.applicationLayoutboolean
blocks.articleboolean
blocks.avatarboolean
blocks.button| boolean | { enabled?: boolean icon?: string }
blocks.cardboolean
blocks.carousel| boolean | { enabled?: boolean wrapperPrevIcon?: string wrapperNextIcon?: string bottomPrevIcon?: string bottomNextIcon?: string }
blocks.chipboolean
blocks.columns| boolean | { enabled?: boolean count?: number }
blocks.containerboolean
blocks.cookieConsentboolean
blocks.featureboolean
blocks.figureboolean
blocks.footerboolean
blocks.form| boolean | { enabled?: boolean selectIcon?: string checkboxIcon?: string }
blocks.gallery| boolean | { enabled?: boolean prevIcon?: string nextIcon?: string }
blocks.gapboolean
blocks.grid| boolean | { enabled?: boolean paddingCols?: number }
blocks.header| boolean | { enabled?: boolean subNavigationIcon?: string menuIcon?: | { type: 'animated' } | { type: 'static' openIcon?: string closeIcon?: string } }
blocks.heroboolean
blocks.iconboolean
blocks.layoutboolean
blocks.linkboolean
blocks.list| boolean | { enabled?: boolean checkedIcon?: string uncheckedIcon?: string }
blocks.media| boolean | { enabled?: boolean overlayIcon?: string }
blocks.postsbooleanPosts-module presentation CSS (cards, highlight, meta, listing, archive filter, share buttons).
blocks.quote| boolean | { enabled?: boolean icon?: string }
blocks.richtextboolean
blocks.rootVariablesboolean
blocks.sectionboolean
blocks.separatorboolean
blocks.stackboolean
blocks.swiperboolean
blocks.typographyboolean
blocks.variablesUtilitiesboolean
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.categoriesPartial<Record<SysthemaCookieCategoryId, SysthemaCookieCategoryConfig>>
cookieConsent.cookie{ name?: string; expiresAfterDays?: number }
cookieConsent.cookiesSysthemaCookieEntry[]
cookieConsent.defaultLanguagestring
cookieConsent.enabledbooleanMaster switch.
cookieConsent.guiOptionsanyPass-through to vanilla-cookieconsent's guiOptions.
cookieConsent.hideFromBotsbooleanPass-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.policyLinksArray<{ /** 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.reopenSelectorstring | falseSelector that opens the preferences modal on click.
cookieConsent.scanner{ include?: string[] exclude?: string[] /** Override the bundled OCDB. URL or local path. */ databaseUrl?: string }
cookieConsent.themestringOverride the banner's color theme independently from the page.
cookieConsent.translationsRecord<string, SysthemaCookieConsentTranslation>
cookieConsentSysthemaCookieConsentConfig
customTokens.colorPrimitivesRecord<string, unknown>
customTokens.colorSystemRecord<string, unknown>
customTokens.fontRecord<string, unknown>
customTokens.responsiveSizingRecord<string, unknown>
customTokens.textStylesRecord<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.defaultstring
locales.fallbackboolean
locales.missingReadonly<Record<string, 'notFound' | 'fallback' | 'redirect'>>Non-default locales with an EXPLICIT missing-translation override (including an explicit 'notFound').
locales.routingReadonly<{ 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.rtlreadonly string[]
locales.supportedreadonly string[]
localesSysthemaLocalesOptional frontend locale contract.
manifestany
messages.catalogsReadonly<Record<string, Readonly<Record<string, unknown>>>>
messages.fallback'en'Explicitly use the shipped English catalog for unregistered locales.
messagesSysthemaFrontendMessagesFrontend UI message catalogs, read from config at render time (no generated seam).
optimization.mergeThemeDuplicatesboolean
optimization.obfuscateClassesboolean | SysthemaObfuscationStyleClass-name obfuscation.
optimization.obfuscateVariablesboolean | SysthemaObfuscationStyleCSS variable-name obfuscation.
optimization.pruneUnchangedBreakpointsboolean
optimization.variableReferencesResolutionboolean
optimizationboolean | 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.scalenumber
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.excludestring | string[] | false['feature.mediaMinHeight']Property paths/patterns to exclude from spacing transformation.
spacing.functionstring"--spacing(%value% / 4)"Template string for spacing value transformation.
spacing.includestring | string[] | false['grid', 'gap', 'container', 'section', 'article', 'feature']Paths/patterns to transform within each screen size object in responsiveSizing.
spacing.swapbooleanfalseWhen true, stores only the raw numeric value in :root variables.
spacingSpacingRule | 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

systhema.config.ts
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