Design tokens
Design tokens are the values shared across the site: colors, spacing, text, fonts, radii, shadows and containers.
On this page
01Overview
Design tokens are the values shared across the site: colors, spacing, the text scale, fonts, radii, shadows and containers. The option nucleo_tokens stores only the values changed from the defaults. The plugin merges them with the defaults.
A document cites a token with the form $group.key, for example $color.primary. The compiler replaces it with var(--nc-group-key).
The plugin writes the tokens artifact: the @font-face rules of the imported fonts and a :root block with all the variables. The frontend adds this CSS inline before any other style. The nucleo-canvas theme reads the same variables in base.css.
Fonts come from Google Fonts, but the plugin stores them locally. Visitors do not contact Google.
Agents read and write tokens with nucleo/tokens-get and nucleo/tokens-set. The local CLI suggests tokens from an HTML file with nucleo tokens suggest.
02Token groups
The groups are fixed: color, space, text, font, radius, shadow, container. A different group returns invalid_tokens.
Each group has default keys. You can add new keys (see New keys).
color group
What it does: defines the colors of the site.
How to use it: $color.primary in a style value. Variable: --nc-color-primary.
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
primary | string | CSS color (see below) | #2563eb | |
secondary | string | CSS color | #0f766e | |
accent | string | CSS color | #b45309 | |
text | string | CSS color | #1a1a1a | |
muted | string | CSS color | #4a4a4a | |
background | string | CSS color | #ffffff | |
surface | string | CSS color | #f5f5f5 | |
border | string | CSS color | #d4d4d4 |
Accepted formats: hexadecimal with 3, 4, 6 or 8 digits; rgb(), rgba(), hsl(), hsla(), hwb(), lab(), lch(), oklab(), oklch(); var(--nc-…); the words transparent, currentColor and the 16 basic CSS names (black, silver, gray, white, maroon, red, purple, fuchsia, green, lime, olive, yellow, navy, blue, teal, aqua).
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: other CSS names (for example orange) are rejected. Inside color functions only digits, ., %, ,, space, /, - and deg are allowed. The Design system admin page accepts only #rgb and #rrggbb (see Design system page).
space group
What it does: defines the spacing scale for padding, margin and gap.
How to use it: $space.4. Variable: --nc-space-4, value 1rem.
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
0 | number | rem, >= 0 | 0 | |
1 | number | rem, >= 0 | 0.25 | |
2 | number | rem, >= 0 | 0.5 | |
3 | number | rem, >= 0 | 0.75 | |
4 | number | rem, >= 0 | 1 | |
5 | number | rem, >= 0 | 1.25 | |
6 | number | rem, >= 0 | 1.5 | |
8 | number | rem, >= 0 | 2 | |
10 | number | rem, >= 0 | 2.5 | |
12 | number | rem, >= 0 | 3 | |
16 | number | rem, >= 0 | 4 |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: the value is a number, not a string: "1rem" is rejected. 1 rem equals 16 px.
text group
What it does: defines the scale of body text, fluid between two values.
How to use it: $text.xl. Variable: --nc-text-xl, with clamp() (see Fluid text with clamp()).
Parameters:
| Key | Type | Allowed values | Default [min, max] rem | Notes |
|---|---|---|---|---|
xs | pair of numbers | 0 <= min <= max | [0.75, 0.875] | |
sm | pair of numbers | 0 <= min <= max | [0.875, 1] | |
base | pair of numbers | 0 <= min <= max | [1, 1.125] | |
lg | pair of numbers | 0 <= min <= max | [1.125, 1.375] | |
xl | pair of numbers | 0 <= min <= max | [1.25, 1.625] | |
2xl | pair of numbers | 0 <= min <= max | [1.5, 2] | |
3xl | pair of numbers | 0 <= min <= max | [1.875, 2.5] | |
4xl | pair of numbers | 0 <= min <= max | [2.25, 3] | |
5xl | pair of numbers | 0 <= min <= max | [3, 4] | |
6xl | pair of numbers | 0 <= min <= max | [3.75, 5] |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: the pair must have exactly two numbers. With min equal to max the variable has a fixed value. The raw value of the token is the maximum.
font group
What it does: defines the font families of the text and the headings.
How to use it: $font.heading. Variable: --nc-font-heading.
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
body | string | CSS font stack | system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif | |
heading | string | CSS font stack | ui-serif, Georgia, "Times New Roman", serif |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: the value follows the rules for document style values (see Group validation). Importing a font does not change this group: the family name must be written with nucleo/tokens-set.
radius group
What it does: defines the corner radii.
How to use it: $radius.md. Variable: --nc-radius-md.
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
sm | string | CSS value | 0.25rem | |
md | string | CSS value | 0.5rem | |
lg | string | CSS value | 1rem | |
full | string | CSS value | 9999px |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: the code does not check that the value is a length. It only checks the safety of the CSS text.
shadow group
What it does: defines the shadows.
How to use it: $shadow.md. Variable: --nc-shadow-md.
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
sm | string | CSS value | 0 1px 2px rgba(0,0,0,0.05) | |
md | string | CSS value | 0 4px 6px -1px rgba(0,0,0,0.1) | |
lg | string | CSS value | 0 10px 15px -3px rgba(0,0,0,0.1) |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: commas are allowed, so two shadows in one token are valid.
container group
What it does: defines the maximum widths of the containers.
How to use it: $container.lg. Variable: --nc-container-lg, value 1024px. The inner box of nc/section uses max-width: var(--nc-container-lg).
Parameters:
| Key | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
sm | integer | px, > 0 | 640 | |
md | integer | px, > 0 | 768 | |
lg | integer | px, > 0 | 1024 | width of nc/section |
xl | integer | px, > 0 | 1280 |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: the value must be an integer. A decimal number, even 1200.0, is rejected.
New keys
What it does: extends the scale of a group with a key the defaults do not have, for example $space.20 or $color.brand-dark.
How to use it: nucleo/tokens-set with {"tokens": {"space": {"20": 6}}}. The token $space.20 equals 6rem.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
| key | string | [a-z0-9-], 1 to 24 characters | lowercase letters, digits, - | |
| value | depends on the group | group rules |
Permissions: as nucleo/tokens-set.
Edition: Free
Known limits: at most 48 keys per group, defaults included. Default keys cannot be removed: null resets them to the default. The reference in a document follows the form $[a-z]+.[a-z0-9-]+.
03Validation
Group validation
What it does: merges the given values with the defaults and checks each value. An error saves nothing and returns the code invalid_tokens.
How to use it: internal. It is called by nucleo/tokens-set, the import of site.json and the application of a kit.
Parameters: rules per group.
| Group | Rule | Error message |
|---|---|---|
space | integer or finite decimal number, >= 0 | expected a number of rem >= 0 |
text | [min, max] pair of numbers, 0 <= min <= max | expected a [minRem, maxRem] pair with 0 <= min <= max |
container | integer > 0 | expected an integer in px > 0 |
color | formats of the color group | expected a valid CSS color |
font, radius, shadow | non-empty string that passes the CSS value check | invalid CSS value |
The CSS value check rejects ;, {, }, <, >, \, control characters, /* */ comments, url(, expression(, @import, image-set(, image(, cross-fade(, element(, src(, javascript: and unclosed brackets or quotes.
Permissions: none at this level.
Edition: Free
Known limits:
- Unknown group:
Unknown token group: <group>. - Group not an object:
Group <group> must be an array. - Invalid key:
Invalid token key. - Too many keys:
Too many tokens in group <group> (maximum 48). - If the saved option is invalid, the plugin uses the defaults without an error.
Token references in documents
What it does: the document validator rejects a $group.key that does not exist in the site's tokens. The compiler replaces tokens also inside composite values, for example 1px solid $color.border.
How to use it: write the token in the style value, for example "padding": "$space.12 0".
Parameters: none.
Permissions: those of saving the document.
Edition: Free
Known limits: validation error unknown token: $space.20, with the suggestion to use nucleo/tokens-get or nucleo/tokens-set. In the compiler, a declaration with an unknown token is dropped.
Removing a token with tokens-set does not re-check the documents that use it.
Quality rule style.token.literal
What it does: flags a literal style value equal to a token's value. The value should be written as a reference to the token.
How to use it: automatic in the quality engine.
Parameters: properties checked per group.
| Group | Properties |
|---|---|
color | color, background, accentColor, itemColor, itemColorHover, itemColorActive, itemBackground, itemBackgroundHover, itemBackgroundActive, submenuBackground, panelBackground and the color keys of the block parts |
space | padding, margin, gap, itemPadding, itemGap and the spacing keys of the block parts |
radius | borderRadius, itemRadius and the radius keys of the block parts |
shadow | boxShadow |
font | fontFamily and the font keys of the block parts |
State keys (for example colorHover) use the group of the base key.
Permissions: none.
Edition: Free
Known limits:
- Severity
error, so it blocks publication until a person reviews it. - The comparison is on the whole value: it does not find tokens inside composite values.
pxandremare compared in rem (16 px = 1 rem). Zero does not count.#abcequals#aabbcc.- The
textandcontainergroups are not checked.
04CSS output
CSS variables in :root
What it does: writes a minified :root{…} block with one variable for each key of each group.
How to use it: the name is --nc-<group>-<key>. Examples: --nc-color-primary:#2563eb, --nc-space-4:1rem, --nc-container-lg:1024px.
Parameters: value conversion.
| Group | Output |
|---|---|
space | number + rem |
text | clamp(...), or a fixed value if min = max |
container | number + px |
color, font, radius, shadow | text unchanged |
Permissions: none.
Edition: Free
Known limits: numbers have at most 4 decimals, without trailing zeros.
Fluid text with clamp()
What it does: converts the [min, max] pair of the text group into a text size that grows with the width of the window.
How to use it: automatic. Example for base with the defaults: --nc-text-base:clamp(1rem, calc(0.9712rem + 0.1282vw), 1.125rem).
Parameters: minimum viewport 360 px, maximum viewport 1920 px, 1 rem = 16 px.
Permissions: none.
Edition: Free
Known limits: the two viewport limits are constants in the code. They are not configurable.
Publishing the tokens artifact
What it does: writes the tokens artifact with three fields: css, version (first 8 characters of the SHA-1 of the CSS) and preload (list of URLs of the fonts to preload, at most two).
How to use it: automatic. It runs after tokens-set, after fonts-import, on plugin activation, after the import of site.json and in the store maintenance in admin.
Parameters: none.
Permissions: those of the operation that starts it.
Edition: Free
Known limits: the CSS contains first the @font-face rules of the imported fonts, then the fallback @font-face rules, then the :root block. In the font stacks it adds the metric fallback font after the first family; the saved option does not change. The code does not recompile the documents when tokens change.
Frontend loading
What it does: the frontend registers the style nucleo-tokens and adds the artifact as inline CSS. It is queued before the other styles.
How to use it: automatic on pages built with Nucleo. On other pages the frontend queues it when a layout (header, footer) applies.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: no CSS if the artifact is missing or empty. The nucleo-canvas theme uses the variables in base.css with a fallback value, for example var(--nc-color-primary,#2563eb). Editor previews receive the same CSS in the field tokensCss.
Exposure to Gutenberg and theme.json
What it does: produces a theme.json version 3 array: color.palette from the colors, typography.fontSizes from the text (with fluid min and max), typography.fontFamilies from the fonts, spacing.spacingSizes from the spacing, layout.contentSize from container.lg and layout.wideSize from container.xl. At each publication the array is saved in the option nucleo_theme_json.
How to use it: automatic. The array is refreshed at each publication of the tokens artifact.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: Gutenberg receives the tokens only with the nucleo-canvas theme: the theme reads nucleo_theme_json in the wp_theme_json_data_theme filter. With other themes the tokens do not reach the block editor. The radius and shadow groups are not in the export.
05Fonts
Import from Google Fonts
What it does: downloads a Google Fonts family and stores it locally as woff2 files. Registers the faces in the option nucleo_fonts (autoload off) and republishes the tokens artifact.
How to use it: ability nucleo/fonts-import, or the Design system admin page, Typography tab, panel "Import from Google Fonts".
Parameters: see nucleo/fonts-import.
Permissions: edit_theme_options.
Edition: Free
Known limits:
- CSS from
https://fonts.googleapis.com/css2, files only fromhttps://fonts.gstatic.com. Another host givesfont_host_rejected. - Timeout 10 seconds, no redirects, maximum 2 MB per response (
font_too_large). - The file must start with the signature
wOF2, otherwisefont_format. If the response has no allowed subset, alsofont_format. - Downloaded subsets:
latinandlatin-extby default. The optionnucleo_font_subsetsgives the starting list (lowercase values, letters a-z, digits and hyphen; an empty or invalid value falls back to the default); the filternucleo/font_subsetshas the last word. Each subset is one more download. - Folder:
uploads/nucleo/fonts/. File name:<slug>-<weight>-<style>[-<subset>].woff2. - A new import of the same family (case-insensitive comparison) replaces the faces and deletes the old files.
- No function removes an imported font.
- Other error codes:
invalid_family,invalid_weights,font_network,uploads_unavailable,font_write.
Local @font-face rules
What it does: generates an @font-face rule for each installed file, with font-display:swap and unicode-range when present.
How to use it: automatic, inside the tokens artifact.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: malformed nucleo_fonts entries (family, weight, style, URL or range not valid) are ignored.
Metric fallback font
What it does: creates a family '<Family> Fallback' based on a local font, with size-adjust, ascent-override, descent-override and line-gap-override. It reduces layout shift while the font loads.
How to use it: automatic. The fallback follows the category of the family: Arial for sans-serif, Times New Roman for serif, Courier New for monospace.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: it works only for families present in the plugin's metrics data (from @capsizecss/metrics 3.7.0). The fallback @font-face rule exists only for imported families. The fallback name enters the font stacks for each first family with metrics.
Preload of the fonts
What it does: chooses up to two files to preload and sends them in the HTTP header Link: <url>; rel=preload; as=font; type="font/woff2"; crossorigin.
How to use it: automatic. The file is the one of the first family of font.body that is imported: weight 400 normal if it exists, otherwise the first face of the family. The second is the weight 700 file of font.heading, if that family is imported. Duplicate URLs are removed.
Parameters: none.
Permissions: none.
Edition: Free
Known limits: preloads at most two files, without duplicates. If font.body does not use imported fonts, the first file is the first installed face of any family. The header is sent only on pages built with Nucleo and only if the headers have not already been sent.
06Abilities and commands
nucleo/tokens-get
What it does: returns the effective tokens of the site, defaults included, grouped by group.
How to use it: ability via MCP. Full entry in Read abilities.
Parameters: none. Output {"ok": true, "tokens": {…}}.
Permissions: edit_posts; scope nucleo:read.
Edition: Free
Known limits: none found.
nucleo/tokens-set
What it does: merges the submitted values with the saved tokens, validates, saves the option nucleo_tokens and republishes the tokens artifact.
How to use it: ability via MCP, or the Design system admin page. Full entry in Write abilities. Example: {"tokens": {"color": {"primary": "#1d4ed8"}, "text": {"xl": [1.25, 1.5]}}}.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
tokens | object | groups and keys of this chapter | required | send only the keys to change; null removes the key |
Permissions: edit_theme_options; scope nucleo:design.
Edition: Free
Known limits: an invalid value returns {"ok": false, "error": {"code": "invalid_tokens", …}} and saves nothing. tokens not an object: invalid_input. The result contains contrast: the contrast problems the new tokens cause in published documents (up to 50 documents). Saving is not blocked by contrast. The operation appears in the activity log as tokens-set.
nucleo/fonts-import
What it does: imports a Google Fonts family locally and republishes the tokens.
How to use it: ability via MCP, or the Design system admin page. Full entry in Write abilities. Example: {"family": "Inter", "weights": [400, 700]}.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
family | string | letters and digits, words separated by one space, up to 8 words | required | |
weights | array of integers | multiples of 100 from 100 to 900, from 1 to 9 values | required | duplicates removed |
italic | boolean | true, false | false | true downloads only the italic variants |
Permissions: edit_theme_options; scope nucleo:design.
Edition: Free
Known limits: the output faces contains family, weight, style and url. The path on the server is not returned. Errors return ok: false with the codes of Import from Google Fonts. The admin page limits the weights to 6.
Reference nucleo/catalog-get with topic: tokens
What it does: returns the token rules for agents: groups, formats, variable names, behavior of tokens-set. In data there are the default keys (keys), the defaults (defaults) and the site's saved tokens (current).
How to use it: nucleo/catalog-get with {"topic": "tokens"}. See Read abilities.
Parameters: topic = tokens.
Permissions: edit_posts; scope nucleo:read.
Edition: Free
Known limits: the text says that theme.json receives contentSize and wideSize. The array is saved in the option nucleo_theme_json at each publication (see Exposure to Gutenberg and theme.json).
nucleo tokens suggest
What it does: reads an HTML file and proposes the input of nucleo/tokens-set. It considers values repeated at least 3 times in <style> elements and in style="" attributes.
How to use it: nucleo tokens suggest <design.html>. The standard output contains only {"tokens": {…}}. The standard error lists the evidence (color.primary: #a4462a (7)) and the values without a token (no token: …). See Local CLI.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
<design.html> | path | HTML file | required | one argument only |
Permissions: none. The command does not contact the site and does not write files.
Edition: Free
Known limits:
- Colors: only
#rgb,#rrggbb,rgb(),rgba(),hsl(),hsla()in color properties. Keys are chosen by lightness and saturation. Shadows do not generate colors. - Spacing and text: only
pxandrem, assigned to the nearest default key. Text comes out as a fixed pair[v, v]. - Radii:
sm,md,lgandfull(from 999 px or50%). Shadows:sm,md,lg. - Fonts:
bodyis the most frequent,headingthe most used in heading selectors. - Durations of
transitionandanimationalways end up inno token: the system has no group for durations. - Scripts and
@font-facerules are ignored. With at least 3 defined CSS variables, the command reads the variables and ignores the rules that do not style the markup. - Different arguments give
Usage: nucleo tokens suggest <design.html>.
nucleo push --use-tokens
What it does: before the push, replaces in the local files the values equal to a token with $group.key.
How to use it: nucleo push [dir] --use-tokens. With --dry-run it counts the replacements without writing. See Local CLI.
Parameters: none beyond those of push.
Permissions: those of nucleo/tokens-get (edit_posts; scope nucleo:read) plus those of the push.
Edition: Free
Known limits: it compares with the site's tokens overridden by the tokens of the local site.json. The properties per group match those of the rule style.token.literal; the parity tests verify this match.
07Admin page
Design system page
What it does: shows and edits the tokens in the admin page "Design system" (slug nucleo-design). It has five tabs: Colors, Typography, Spaces, Shapes, Containers.
How to use it: Nucleo AI → Design system. The page reads with nucleo/tokens-get and saves with nucleo/tokens-set, sending only the changed values.
Parameters: what can be changed per tab.
| Tab | Editable | Read only |
|---|---|---|
| Colors | hexadecimal value of each color | contrast table, preview |
| Typography | font.body, font.heading, text scale (minimum and maximum), Google Fonts import | |
| Spaces | space scale | |
| Shapes | radius, shadow | |
| Containers | container |
Permissions: edit_theme_options.
Edition: Free
Known limits:
- Colors accept only
#rgband#rrggbb. A color saved in another format (for examplergb()) is an error and blocks saving. - The text scale expects numbers greater than zero; the server also accepts zero.
- The "Add custom token" button is disabled.
- The contrast table checks five pairs (
text/background,text/surface,muted/background,muted/surface,background/primary) with a 4.5:1 threshold. - The label says "Fluid between 375 and 1920 px". The server computes the
clamp()between 360 and 1920 px. - After saving, the page shows "Saved. Documents are rebuilding in the background".
Was this page helpful?