API

Configuration: traceless-style.config.js

Optional file at the project root. CommonJS only — traceless-style.config.js, not .mjs or .ts.

Full shape

// traceless-style.config.js
module.exports = {
  /* Source roots to scan. Default: union of `src/` and `app/` if either exists. */
  srcDir: "src",                            // string or string[]

  /* Lint configuration. Default: all rules ON (strict). */
  lint: {
    noInlineStyles: true,                   // cannot be disabled fully
    noClassString:  true,
    noCSSModules:   true,
    noTailwind:     true,
    ignore:         ["**/__tests__/**"],
  },
  // …or `lint: false` to disable noClassString/noCSSModules/noTailwind
  //   (noInlineStyles stays on).

  /* Auto dark-mode derivation. Default: true. */
  autoDarkMode: true,

  /* Auto RTL physical → logical rewriting. Default: true. */
  autoRtl: true,

  /* WCAG contrast validation. Default: AA enforced, strict by default
     (build fails on errors). Set strict: false to demote to warnings. */
  contrast: {
    level:               "AA",          // "AA" | "AAA" | "off"
    strict:              true,          // AA failures → build errors (default true)
    strictAAA:           false,         // AAA failures → build errors
    surfaceLight:        "#fafafa",
    surfaceDark:         "#0a0a0f",
    largeTextSize:       18,            // px threshold for "large text"
    auditUiComponents:   true,          // §1.4.11 — borders, caret, accent, etc.
    auditPlaceholder:    true,          // §1.4.3 for &::placeholder selectors
    gradientSampleCount: 5,             // midpoints between adjacent gradient stops
    suggestionSpace:     "oklch",       // "oklch" | "hsl" — fix-color search space
    auditPeerSurfaces:   false,         // opt-in: cross-validate against sibling bgs
  },

  /* Custom variants — also detected from `tl.extend({ variants })` calls.
     Putting them here is optional; useful when you want them centralized. */
  variants: {
    _tablet: "@media (min-width: 900px)",
  },
};

Key reference

srcDir: string | string[]

Source root(s) to scan. If unset, the CLI scans both src/ and app/ (whichever exist) plus the project root as a final fallback.

lint

See Linting for the full rule list.

KeyTypeDefaultNotes
noInlineStylesbooleantrueCannot be fully disabled — even lint: false keeps this on
noClassStringbooleantrueReject bare className="..." strings
noCSSModulesbooleantrueReject .module.css imports
noTailwindbooleantrueReject Tailwind utility class names
ignorestring[][]Glob patterns to skip

autoDarkMode: boolean

When true (default), the compiler derives a dark-mode variant of every color value in your styles. See Dark mode. Disable via _autoDark: false per group, or globally with autoDarkMode: false.

autoRtl: boolean

When true (default), the compiler rewrites physical CSS properties (marginLeft, paddingRight, etc.) to their logical equivalents. See RTL. Disable per group with _autoRtl: false.

contrast

WCAG 2.1 + 2.2 audit settings. The full feature set is documented in WCAG contrast validation.

KeyTypeDefaultNotes
level"AA" | "AAA" | "off""AA"Highest standard the validator aims for. AA is the legal floor for Section 508 (US) and EN 301 549 (EU).
strictbooleantrueAA failures → build errors. Set false to demote to warnings while migrating an older codebase.
strictAAAbooleanfalseAAA failures → build errors. AAA is best-effort enhancement; many legitimate designs (large hero gradients, decorative chips) fail it.
surfaceLightstring"#fafafa"Assumed light-mode page surface. Used to composite translucent backgrounds before measurement (CSS Color 4 §10).
surfaceDarkstring"#0a0a0f"Assumed dark-mode page surface.
largeTextSizenumber18Pixel threshold above which text qualifies as "large" (3:1 / 4.5:1 instead of 4.5:1 / 7:1). WCAG defines large as ≥18pt regular OR ≥14pt bold.
auditUiComponentsbooleantrueAudit border / outline / caret / accent / text-decoration / box-shadow colors per §1.4.11 (≥3:1).
auditPlaceholderbooleantrueAudit &::placeholder selectors. Placeholder text counts as text under §1.4.3.
gradientSampleCountnumber5When auditing color: transparent + background-clip: text, sample N midpoints between each pair of adjacent gradient stops. Catches low-contrast troughs that lie between two acceptable declared stops. Set to 0 to only check declared stops.
suggestionSpace"hsl" | "oklch""oklch"Color space for the fix-suggestion binary search. OKLCH preserves hue and chroma intent better than HSL — a brand blue stays blue.
auditPeerSurfacesbooleanfalseWhen true, audit a group's color against the backgrounds declared on sibling groups in the same tl.create({...}) call. Catches cross-component contrast bugs but produces false positives on unrelated siblings. Off by default; enable for design-system rigor.

variants

Optional pre-registered custom variants. Same format as tl.extend({ variants: ... }). Most projects prefer the tl.extend form (variant definitions colocated with code).

Environment variables

VariableEffect
TRACELESS_STYLE_PARSERForce parser: "swc" or "legacy". Overrides config.
TRACELESS_STYLE_DEBUG_RESOLVEWhen set to 1, prints the cross-file token export registry after Pass 0. Useful for debugging "my import isn't expanding."

Loading order

The CLI (src/cli/extract.ts) loads config in this order:

  1. Resolve traceless-style.config.js from process.cwd().
  2. If it exists, require() it (with cache-busted re-read for watch mode).
  3. Apply srcDir → CLI SRC_DIRS.
  4. Apply lint → CLI lint runner.
  5. Apply autoDarkMode → setAutoDarkMode(false) if false.
  6. Apply contrast → setContrastOptions(cfg.contrast).

If the config file is missing or malformed, defaults are used silently.

ESM project notes

If your project uses "type": "module" in package.json, name the config explicitly:

  • ✅ traceless-style.config.cjs (CommonJS)
  • ❌ traceless-style.config.mjs (not currently supported — require() cannot load ESM)
  • ❌ traceless-style.config.ts (not currently supported)

The CLI uses Node's require() to load the config — see createRequire(import.meta.url) in src/cli/extract.ts.

See also

See also