NemCSS Configuration
NemCSS is configured via a nemcss.config.json file at the root of your project. Run nemcss init to scaffold one automatically.
Top-level fields
| Field | Type | Default | Description |
|---|---|---|---|
content | string[] | [] | Glob patterns for source files. NemCSS scans these to only generate used utility classes. If empty, no utility classes are generated. |
tokensDir | string | "design-tokens" | Path to the directory containing your token JSON files. |
theme | object | (none) | Token category configuration. Each key is a category name (e.g. colors). |
semantic | object | (none) | Semantic token groups. Optional. See the semantic block. |
The theme block
For each token category, you decide which utility classes to generate. A utility is defined by a prefix (the class name prefix) and a property (the CSS property). One utility class is generated per token in the category. If you don't define any utilities, none are generated. Custom properties are always generated regardless.
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Path to the token JSON file for this category, relative to the project root. |
prefix | string | no | Base name for generated custom properties. "sp" → --sp-xxs, --sp-xs, etc. Defaults to the category name if not set. |
utilities | object[] | no | Utility classes to generate. Each entry has a prefix (class prefix) and property (CSS property). |
Naming
The key you use in theme (e.g. "spacings") is the category name. It is what you reference in semantic token values ({spacings.xxs}). The category name is derived from the token file name without its extension (e.g. spacings.json → "spacings"). The prefix field controls the base name for the generated CSS custom properties. A category "spacings" with "prefix": "sp" produces --sp-xxs, --sp-xs, and so on. If prefix is not set, the category name is used.
Default prefix
For common category names, NemCSS applies a default singularization when prefix is not set: colors → color, spacings → spacing, fonts → font, shadows → shadow, borders → border, radii → radius. For anything else, the category name is used as-is.
Example
{
"theme": {
"colors": {
"source": "design-tokens/colors.json",
"prefix": "color",
"utilities": [
{ "prefix": "text", "property": "color" },
{ "prefix": "bg", "property": "background-color" }
]
}
}
}With a primary token in colors.json, this produces:
:root {
--color-primary: #3b82f6;
}
.text-primary {
color: var(--color-primary);
}
.bg-primary {
background-color: var(--color-primary);
}The property field
The property field accepts any valid CSS property:
{ "prefix": "text", "property": "color" }
{ "prefix": "bg", "property": "background-color" }
{ "prefix": "border", "property": "border-color" }
{ "prefix": "outline", "property": "outline-color" }
{ "prefix": "fill", "property": "fill" }
{ "prefix": "stroke", "property": "stroke" }You can also use a CSS custom property as the target, useful for component-level theming:
{ "prefix": "surface", "property": "--surface-color" }For a primary token this generates:
.surface-primary {
--surface-color: var(--color-primary);
}Components that reference --surface-color can be restyled just by changing which utility class you apply.
The semantic block
The semantic block is optional. It lets you scope a subset of your primitive tokens to a specific role in your UI: text colors, background colors, surface colors, and so on.
Each entry defines a group with an optional CSS property and a tokens map. Token values reference your primitive tokens using the {category.tokenName} syntax.
| Field | Type | Required | Description |
|---|---|---|---|
property | string | no | The CSS property for generated utility classes (e.g. color, background-color). Omit it to generate only the CSS custom properties for this group with no utility classes. |
tokens | object | yes | A map of semantic token names to primitive token references ({category.tokenName}). |
Naming
The key you use in semantic (e.g. "text") determines the base name for both the generated custom properties and utility classes. A group "text" with a token "primary" produces --text-primary and .text-primary.
Example
{
"semantic": {
"text": {
"property": "color",
"tokens": {
"primary": "{colors.blue-600}",
"secondary": "{colors.slate-500}",
"muted": "{colors.slate-400}"
}
}
}
}This generates:
:root {
--text-primary: var(--color-blue-600);
--text-secondary: var(--color-slate-500);
--text-muted: var(--color-slate-400);
}
.text-primary { color: var(--text-primary); }
.text-secondary { color: var(--text-secondary); }
.text-muted { color: var(--text-muted); }All your primitive color custom properties remain available. The semantic layer adds a second, intent-driven layer on top.
Generating only custom properties (no utility classes)
If you only want the semantic CSS variables and don't need utility classes, omit the property field. The group's custom properties are still generated; no utility classes are.
{
"semantic": {
"text": {
"tokens": {
"primary": "{colors.blue-600}",
"secondary": "{colors.slate-500}",
"muted": "{colors.slate-400}"
}
}
}
}This generates only the :root block:
:root {
--text-primary: var(--color-blue-600);
--text-secondary: var(--color-slate-500);
--text-muted: var(--color-slate-400);
}