Contributing
Anyone is welcome to contribute with new design tokens or creating new platform to translate them into. If you’d like to do so sync with the Nucleus guild so they can walk you through the process and document any changes.
Taxonomy
Before getting started, make sure you’re familiar with the format, filepath and naming convention we’re using. Adding tokens that do not follow the same structure can have negative impact on the way they’re distributed across platforms and imported into design tools.
Format
{
"token-name": { // Name matching our convention.
"$type": "color", //One of possible token types defined in DTCG and sd-transforms.
"$value": "{color.white}", // Value, preferably reference or expression.
"$description": "About me", // Can be exported as comment in code.
"$extensions": { // We sometimes add extensions for things like color modifiers.
"org.example.tool-a": 42,
"org.example.tool-b": {
"turn-up-to-11": true
}
}
}
}
We try to stick to W3C DTCG formatting when possible. In addition, Tokens Studio includes some custom token types that haven't been adopted by the standard yet but are under review. Translation configs use sd-transforms to map themes and modes with final variables and resolve more complex expressions.
Filepath
Use following file structure when creating design tokens:
scope / abstraction / component / category / mode
|
Scope |
Usually a platform, f.e. "web, product..." |
|
Abstraction |
Specifies the intended usage. The basic options are primitive, semantic and component abstractions |
|
Component (optional) |
Component attached to these tokens. F.e. "product/component/overlay/colors.json" |
|
Category |
Organises tokens of the parent into logical categories, f.e. ".../colors or dimensions or effects” |
|
Mode (optional) |
For tokens specific for certain mode, f.e. ".../colors/light.json" |
Token naming convention
We try to keep the names similar to legacy platform variables where possible. Some platforms also use different convention for certain token types for easier adoption. When creating new token, try to stick to this format: type / group / variant / sub-type / state
|
Type |
Allows for easier categorization and helps inform users about its intented use, f.e. "color, spacing ..." |
|
Group |
Groups tokens into single logical parent, f.e. "color.background.default" |
|
Variant |
Some groups need second level to make distinction clearer, f.e. "typography.text.large.font-size" |
|
Sub-type |
Certain token types are composite of multiple visual properties, f.e. "typography.text.small.font-size or line-height" |
|
State |
Some tokens provide variable for each state, f.e. "color.status.blue.enabled or hover or focused" |
Notable auxiliary files
- $metadata - Stores load order of token sets in Figma and Tokens Studio. Sets are loaded top-bottom, each set overriding or extending the ones before.
- $themes - Stores definitions of token sets and their modes f.e. default/compact, light/dark...
Design
Designers can request access and editor license to Tokens Studio from the Nucleus guild. Guild will also walk you through the process and best practices and help you make any reviewed changes.
Best design practices
You should always create new branch before modifying any tokens. Figma will try to load your branch even when switching between the files so you can test them out in multiple documents.
We also recommend you test things in new playground files or inside a file branch. Doing changes in the main file could potentially disconnect many variables or conflict with anyone merging changes at the same time.
Once you’re happy with the change, create a pull request for the branch and assign a reviewer from the Nucleus guild. When it’s merged into main branch, you’ll need to update all affected figma libraries and export new version of tokens into each affected platform.
Development
Clone the pb-nucleus-tokens repository to get started. You’ll also find technical documentation inside the repo and can always refer to details there.
Modifying tokens
Design tokens are stored under src/tokens and categorised into scopes and sets. If you’re creating a new set you will also need to assign it to one of the themes defined in $themes.json and add it to token set order $metadata.json in order for designers to get access to them.
Deprecating tokens and groups
When you want to mark token or group of tokens for deprecation, add the $deprecated property and provide reasonable substitute in its description. You can also update the description to make the state more obvious.
{
"radius-xxs": {
"$value": "#777777",
"$type": "color",
"$deprecated": true //While valid value, do not use this.
},
"radius-xs": {
"$value": "#70c0ff",
"$type": "color",
"$deprecated": "Please use {radius-sm} instead."
//Provide reasonable substitute for the deprecated token or group.
}
}
Creating new theme
Themes are defined in $themes.json. Simply add new one and define its token sets. Enabled sets are included, Disabled ignored and Source sets are used as references to resolve semantic values. You can also assign a themegroup, which will make the theme a cousin of the other child themes. When generating exports, this will make the theme one of the possible permutations for that theme group. F.e. adding “new-light” into theme group “product/theme” will create all color theme permutations and add new “new-light” to the index.
Creating new platform
We have a script to bootstrap a new package. Run the following command:
pnpm package:create <package-name>
Replace <package-name> with the desired name for your platform (e.g., android-tokens).
This will create a new directory in packages/ with a package.json and README.md.
Creating new platform token structure
If your package needs custom token files, create them in the appropriate location within the src/tokens directory. Follow the established taxonomy.
Ensure your token files follow the W3C Design Tokens format and the project's naming conventions.
Creating build script
Create a new build script in the src/scripts directory. The script name must be prefixed with build- for it to be automatically detected by the build system.
Example for a new token package:
// src/scripts/build-new-design-tokens.ts
import StyleDictionary from 'style-dictionary';
import { promises as fs } from 'fs';
import path from 'path';
import { sdTransforms } from '@tokens-studio/sd-transforms'; //required transformer
import jsonToTS from 'json-to-ts';
// Define the package output directory
const PACKAGE_DIR = path.resolve(process.cwd(), 'packages/new-design-tokens');
// Configure Style Dictionary
// ...rest of your build configuration...
// Main build function
async function buildTokens() {
// Your build logic here
}
// Execute the build
buildTokens();
Transforming tokens
The only required transporter is sd-transforms. This allows us to collect information from Tokens Studio like theme collections.
You can add any other transformers to get desired output. We store some custom transforms in a separate folder so multiple platforms can share them together.
Building tokens
Once you've set up the files, you can build your new package.
# Build all tokens
pnpm build
If you do not develop on Javascript/Typescript stack, use Docker instead. Make sure docker and jq are installed on your system.
docker build --build-arg NODE_VERSION=$(cat package.json | jq -r '.engines.node' | sed -E 's/^[^0-9.]*([0-9].*)$/\1/') -t pb-nucleus-tokens:latest -f Dockerfile.build . \
&& docker run --rm -v $(pwd):/app -w /app pb-nucleus-tokens:latest
This will run all build scripts, including your new build-new-design-tokens.ts script.
Publishing new version
After running the build:
- Verify the updated artifacts in the packages/ directory.
-
Important: Commit the generated artifacts to version control.
Artifacts are the actual final variables for the platform that are used in development. - Update the version in the package's package.json file (e.g., packages/email-design-tokens/package.json)
- Submit a PR with these changes.
Versioning
Packages follow semantic versioning:
- Major version: Breaking changes to token values or structure.
- Minor version: New tokens added (non-breaking).
- Patch version: Bug fixes or documentation updates.
Automated workflows
The CI will:
- Check for token changes in the src/tokens directory.
- Notify if artifacts haven’t been generated in the packages/ directory.
- Notify if the package version hasn’t been bumped.
- Run validation checks (typecheck, lint, build).
Once merged to the main branch, the CI release workflow will:
- Detect new version changes in package.json.
- Auto publish updated packages to package registry.