What pattern() is

MODERN SYSTEM · 1.2.4

pattern() registers a description + a template (CSS or FSCSS). Elsewhere in the same compile unit, a plain line of text is scored against those descriptions. The best hit at or above the pattern’s threshold is expanded in place.

Unlike @define (exact name + args), patterns are intent-based. From 1.2.4, templates can also pull values out of the caller’s phrase with @match(regex) — so patterns behave like parameterized helpers without a formal signature.

Semantic match

Word overlap / similarity — not only exact strings

Threshold

Per-pattern minimum score (0–1); default 1 if omitted

@match

Capture groups from the call phrase into the template

Compile-time

CLI or runtime expand once — no browser NLP cost in production CSS

Flow: register patterns → write human lines → score → inject template → resolve @match against that line → emit CSS/FSCSS.

Install

npm install fscss@1.2.4
<script src="https://cdn.jsdelivr.net/npm/fscss@1.2.4/runtime.min.js" defer></script>

Use 1.2.4+ for improved matching, balanced-paren @match, and safer regex checks.

Creating & calling patterns

1 Declare

pattern()
pattern(threshold: "description in plain language", `
  /* template: CSS and/or FSCSS */
`)
  • threshold — optional; omit → defaults to 1 (strict)
  • description — words used for similarity scoring
  • template — prefer backticks so quotes inside CSS are free

2 Call

Write a line without typical CSS structure ({ } ; alone as pure CSS). That line is treated as a phrase and compared to descriptions.

create-call.fscss
pattern(0.5: "Hello World card", `
  border-radius: 12px;
  padding: 24px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: #fff;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
`)

.card {
  hello world card
}

The phrase sits inside a selector (property pattern) or alone (block pattern — see below).

Thresholds & sensitive patterns

How strict should a listener be?

sensitivity

Similarity is word-based (case-insensitive). A phrase must score ≥ threshold and beat other candidates.

Threshold Behavior Use for
1 (default) Near-exact description Short / generic phrases (“dark button”)
0.7–0.9 Strict but forgiving typos/order Named components
0.4–0.6 Looser intent match Longer descriptions with optional words
≤ 0.35 Very open — easy collisions Rare; keep descriptions unique

Sensitive (high)

pattern(0.9: "primary cta button solid", `
  background: #4f46e5;
  color: #fff;
  border-radius: 8px;
`)
/* Only close paraphrases of that phrase fire */

Open (lower)

pattern(0.5: "Beautiful card", `
  background: #06f;
`)
/* "beautiful card", "a beautiful card panel" may match */
Collisions: Overlapping descriptions + low thresholds cause the wrong template to win. Prefer distinct verbs/nouns (“render chart” vs “create array”).

@match — parameters from the phrase

Parameterized patterns without formal args

@match

Inside a template, @match(regex) runs against the caller’s phrase (not the description). The first defined capturing group is used; if none, the full match. Parentheses in the regex are supported via balanced scanning (inner ) won’t truncate the directive).

match-button.fscss
pattern(0.6: "rounded primary button with color: white, bg: red", `
  background: @match(background:?\s([#\w\d-_]+)) @match(bg:?\s([#\w\d-_]+));
  color: @match(color:?\s([#\w\d-_]+)) @match(text:?\s([#\w\d-_]+));
  border-radius: 25px;
  padding: 10px 20px;
  border: 2px solid;
  font-weight: 700;
`)

.primary {
  rounded primary button with color: #0BCEAE, background: midnightblue
}

Designing “inputs”

  • Put stable keywords in the description (for scoring).
  • Put variable slots in the call phrase and harvest with @match.
  • Offer alternate labels in one pattern: bg: and background:, color: and text:.
  • If a match fails, the insertion is empty (unless strict mode is enabled in the engine options).
array + values
pattern(0.35: "create sales array value: 0,", `
@arr @match(create\s([\w-_]+))[
  @match(data:?\s([\d\, \s]+))@match(value:?\s([\d\, \s]+))
]
`)

create sample array value: 77, 7, 66, 78, 16
/* → @arr sample[ 77, 7, 66, 78, 16 ] when groups resolve */

Property patterns vs block patterns

Property

Phrase inside a rule → declarations merge into that rule.

.btn {
  rounded primary button
}

Block

Phrase alone → full constructs (@keyframes, top-level FSCSS, etc.).

pattern(0.7: "animated keyframe for spin", `
@keyframes spin {
  to { transform: rotate(360deg); }
}
`)

an Animated keyframes for spin

Patterns that emit FSCSS

Arrays, modules, st-core

Templates are not limited to plain CSS. They can expand to @arr, @import, or module calls — then the rest of the pipeline runs as usual.

st-core-pattern.fscss
@import((*) from st-core@v2)
@st-root()

pattern(0.35: "create sales array value: 0,", `
@arr @match(create\s([\w-_]+))[
@match(data:?\s([\d\, \s]+))@match(value:?\s([\d\, \s]+))
]
`)

pattern(0.50: "render sales chart with st-core ", `
@st-chart-fill(.fill, @match(st-core\s([\w-_]+))@match(render\s([\w-_]+)))
@st-chart-line(.line, @match(st-core\s([\w-_]+))@match(render\s([\w-_]+)))
.chart {
  @st-chart-points(@match(st-core\s([\w-_]+))@match(render\s([\w-_]+)))
}
`)

create sample array value: 77, 7, 66, 78, 16
render sample chart with st-core

.chart {
  width: 300px;
  height: 200px;
  position: relative;
  border: 1px solid var(--st-muted);
  border-radius: var(--st-radius-md);
  background: var(--st-surface);
}

Description words (“create”, “render”, “st-core”) drive matching; @match binds the name token (sample) into array and chart helpers.

Safe @match regexes

1.2.4 rejects dangerous or invalid sources before new RegExp:

  • Nested quantifiers such as (a+)+
  • Hostile repeated alternation forms
  • Overlong sources (sanity cap)
  • Invalid syntax → clear compile error

Prefer simple character classes and one clear capturing group per @match.

Advanced recipes

Library file of patterns

/* _patterns.fscss — import into apps */
pattern(0.75: "glass panel elevated", `
  background: color-mix(in srgb, #fff 12%, transparent);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 16px;
`)

pattern(0.8: "muted label uppercase", `
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--st-muted, #64748b);
`)

Ship next to modules so teams type intent instead of copying declarations.

Multiple @match fallbacks

Chain alternate labels so authors can say bg: or background::

background: @match(background:?\s([#\w]+)) @match(bg:?\s([#\w]+));

Whichever group hits the phrase contributes; the other stays empty.

pattern vs @define

@define pattern()
Exact name @name(args) Fuzzy phrase match
@use(param) formal params @match from free text
Best for APIs & modules Best for intent, demos, authoring UX

Best practices

Distinct descriptions

Avoid two patterns that share the same core words at low thresholds

Tune thresholds

Short phrases → high threshold; long unique blurbs → can go lower

One capture per concern

Keep @match regexes small and readable

Backtick templates

CSS can contain ' and " freely

1.2.4: npm install fscss@1.2.4 · CDN https://cdn.jsdelivr.net/npm/fscss@1.2.4/runtime.min.js