Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Welcome to the Specify docs! Learn about how to use and integrate Specify in your workflow to sync your design tokens and assets in your design system.

This template helps you pull your design tokens in the SDTF format in a JSON file.
{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens in SDTF",
"parsers": [
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "output/tokens.json"
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"rules": [
{
"name": "Generate tokens in JSON",
"parsers": [
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "output/tokens.json"
}
}
]
}
]
}This template helps you generate your design tokens as a Tailwind theme.















{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens as a Tailwind theme",
"parsers": [
{
"name": "to-tailwind",
"output": {
"type": "file",
"filePath": "theme.js"
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"rules": [
{
"name": "Generate tokens as a Tailwind theme",
"parsers": [
{
"name": "to-tailwind",
"output": {
"type": "file",
"filePath": "theme.js"
}
}
]
}
]
}npm install -g @specifyapp/cliyarn global add @specifyapp/clispecify initmodule.exports = {
repository: '@workspace/repository',
personalAccessToken: '<your-personal-access-token>',
rules: [],
};{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": []
}module.exports = {
repository: '@workspace/repository',
personalAccessToken: '<your-personal-access-token>',
rules: [],
};{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": []
}specify pullinterface parser {
name: 'select-modes';
options: {
modes: string[];
};
}




{
"colors": {
"$collection": {
"$modes": ["light", "dark"]
},
"info": {
"infoToken": {
"$type": "color",
"$value": {
"light": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
},
"dark": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
}
}
}
},
"danger": {
"dangerToken": {
"$type": "color",
"$value": {
"light": {
"model": "rgb",
"red": 209,
"green": 204,
"blue": 204,
"alpha": 1
},
"dark": {
"model": "rgb",
"red": 19,
"green": 34,
"blue": 54,
"alpha": 1
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Only get tokens from the mode named 'light' and gererate tokens in CSS",
"parsers": [
{
"name": "select-modes",
"options": {
"modes": ["light"]
}
},
{
"name": "to-css-custom-properties",
"options": {
"selectorTemplate": "[data-theme=\"{{mode}}\"]"
},
"output": {
"type": "file",
"filePath": "public/css-custom-properties.css"
}
}
]
}
]
}[data-theme="light"] {
--danger-dangerToken: rgb(209, 204, 204);
--info-infoToken: rgb(219, 234, 254);
}SPECIFY_TOKEN=ab83f8f49f5c65456c7b1fe70efbc804aa08f87150214aa984d4125945ed8283bashconst path = require('path');
const envFile = '.env';
require('dotenv').config({ path: path.resolve(process.cwd(), envFile) });
module.exports = {
repository: '@workspace/repository',
personalAccessToken: process.env.SPECIFY_TOKEN,
rules: [],
};specify pull -p $SPECIFY_TOKENIn this guide you’ll learn how to transform design data coming from Figma Variables, Figma Styles and/or Tokens Studio into CSS Custom Properties using the Specify CLI.
interface parser {
name: 'to-css-custom-properties';
output: {
type: 'file';
filePath: string;
};
options?: {
tokenNameTemplate?: string;
selectorTemplate?: string;
includeCoreTokensInScopes?: boolean;
};
}npm install @specifyapp/cli yarn global add @specifyapp/cli

{
// Response
}{
// Response
}{
// Response
}{
// Response
}{
// Response
}curl -X POST 'https://api.specifyapp.com/repository/@acme-inc/all-design-data/design-tokens' \
-H 'Authorization: <your-personal-access-token>' \
-H 'Content-Type: application/json' \
-d '{"filter": { "types": ["color"]}, "parsers": [{"name": "to-css-custom-properties"}]}'{
"colors": {
"$collection": { "$modes": ["Light", "Dark"] },
"core": {
"blue-100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 219,
"blue": 254,
"alpha": 1,
"green": 236,
"model": "rgb"
},
"Dark": {
"red": 41,
"blue": 67,
"alpha": 1,
"green": 52,
"model": "rgb"
}
}
},
"blue-700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 17,
"blue": 249,
"alpha": 1,
"green": 125,
"model": "rgb"
},
"Dark": {
"red": 96,
"blue": 250,
"alpha": 1,
"green": 168,
"model": "rgb"
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"Dark": {
"$mode": "Dark",
"$alias": "colors.core.blue-100"
},
"Light": {
"$mode": "Light",
"$alias": "colors.core.blue-700"
}
}
}
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens as CSS Custom Properties",
"parsers": [
{
"name": "to-css-custom-properties",
"output": {
"type": "file",
"filePath": "tokens.css"
},
"options": {
"tokenNameTemplate": "--{{groups}}-{{token}}",
"selectorTemplate": "[data-theme=\"{{mode}}\"]",
"includeCoreTokensInScopes": true
}
}
]
}
]
}[data-theme="dark"] {
--core-blue-100: rgb(41, 52, 67);
--core-blue-700: rgb(96, 168, 250);
--semantic-background-button-primary-hover: var(--core-blue-100);
}
[data-theme="light"] {
--core-blue-100: rgb(219, 236, 254);
--core-blue-700: rgb(17, 125, 249);
--semantic-background-button-primary-hover: var(--core-blue-700);
}npm install -g @specifyapp/cliyarn global add @specifyapp/clispecify initspecify pull [flags]specify sync [flags]pathoutput{
"colors": {


This parser helps you get your design tokens as a SDTF graph in JSON.
{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "CSS Styles",
"parsers": [
{
"name": "to-css-custom-properties",
"output": {
"type":"file",
"filePath": "style.css"
}
}
]
},
{
"name": "Raw SDTF",
"parsers": [
{
"name": "to-sdtf",
"output": {
"type":"file",
"filePath": "raw.json"
}
}
]
}
]
}:root[data-Colors="Dark"] {
--Core-Label-blue-base: rgb(96, 168, 250);
--Aliases-Icon-info: var(--Core-Label-blue-base);
--Core-Label-red-base: rgb(221, 72, 64);
--Aliases-Icon-error: var(--Core-Label-red-base);
--Core-Neutral-neutral-6: rgb(174, 178, 183);
--Aliases-Icon-default: var(--Core-Neutral-neutral-6);
--Core-Label-green-base: rgb(125, 216, 121);
--Aliases-Icon-success: var(--Core-Label-green-base);
--Core-Label-orange-base: rgb(255, 158, 41);
--Aliases-Icon-warning: var(--Core-Label-orange-base);
--Core-Neutral-neutral-3: rgb(68, 71, 75);
--Aliases-Icon-disabled: var(--Core-Neutral-neutral-3);
--Core-Primary-app-base: rgb(98, 77, 227);
--Aliases-Icon-selected: var(--Core-Primary-app-base);
}
:root[data-Dimensions="Mobile"] {
--Base-dimension-02: 2px;
--Radii-radius-01: var(--Base-dimension-02);
--Base-dimension-08: 8px;
--Radii-radius-02: var(--Base-dimension-08);
--Base-dimension-04: 4px;
--Base-dimension-12: 12px;
--Base-dimension-16: 16px;
--Base-dimension-24: 24px;
--Base-dimension-32: 32px;
--Spacings-spacing-01: var(--Base-dimension-02);
--Spacings-spacing-02: var(--Base-dimension-04);
--Spacings-spacing-03: var(--Base-dimension-12);
--Spacings-spacing-04: var(--Base-dimension-16);
}
:root[data-Dimensions="Desktop"] {
--Base-dimension-02: 2px;
--Radii-radius-01: var(--Base-dimension-02);
--Base-dimension-08: 8px;
--Radii-radius-02: var(--Base-dimension-08);
--Base-dimension-04: 4px;
--Base-dimension-12: 12px;
--Base-dimension-16: 16px;
--Base-dimension-24: 24px;
--Base-dimension-32: 32px;
--Spacings-spacing-01: var(--Base-dimension-04);
--Spacings-spacing-02: var(--Base-dimension-08);
--Spacings-spacing-03: var(--Base-dimension-12);
--Spacings-spacing-04: var(--Base-dimension-16);
}{
"colors": {
"$collection": { "$modes": ["light", "dark"] },
"core": {
"blue-100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
},
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
}
}
},
"blue-700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
},
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.core.blue-700"
}
}
}
}
}
}
}
}
}
{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate Style Dictionary raw token files",
"parsers": [
{
"name": "to-style-dictionary",
"output": {
"type": "directory",
"directoryPath": "output/tokens/"
}
}
]
}
]
}{
"colors": {
"color": {
"light": {
"core": {
"blue-100": {
"value": "rgb(255, 255, 255)",
"type": "color",
"description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"value": "rgb(255, 200, 255)",
"type": "color",
"description": "token 2 aliased with n modes within collection within n groups"
}
}
}
}
}
}{
"colors": {
"color": {
"dark": {
"core": {
"blue-100": {
"value": "rgb(229, 29, 29)",
"type": "color",
"description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"value": "rgb(229, 0, 0)",
"type": "color",
"description": "token 2 aliased with n modes within collection within n groups"
}
}
}
}
}
}{
"colors": {
"color": {
"light": {
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"value": "{colors.color.light.core.blue-700}",
"type": "color",
"description": "alias token with n modes within collection within n groups"
}
}
}
}
}
}
}
}
}interface parser {
name: 'to-style-dictionary';
output: {
type: 'directory';
directoryPath: string;
};
}{
"Foundation": {
"spacing": {
"1": {
"$type": "dimension",
"$value": {
"default": {
"value": 4,
"unit": "px"
}
}
},
"2": {
"$type": "dimension",
"$value": {
"default": {
"value": 8,
"unit": "px"
}
}
},
"3": {
"$type": "dimension",
"$value": {
"default": {
"value": 12,
"unit": "px"
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Convert spacing in rem and generate tokens in JSON",
"parsers": [
{
"name": "convert-dimension",
"options": {
"toFormat": "rem"
}
},
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}
]
}{
"Foundation": {
"spacing": {
"1": {
"$type": "dimension",
"$value": {
"default": {
"value": 0.25,
"unit": "rem"
}
}
},
"2": {
"$type": "dimension",
"$value": {
"default": {
"value": 0.5,
"unit": "rem"
}
}
},
"3": {
"$type": "dimension",
"$value": {
"default": {
"value": 0.75,
"unit": "rem"
}
}
}
}
}
}interface parser {
name: 'convert-dimension';
options: {
toFormat: '%' | 'px' | 'em' | 'rem' | 'pt' | 'pc' | 'in' | 'cm' | 'mm' | 'ex' | 'cap' | 'ch' | 'ic' | 'lh' | 'rlh' | 'vw' | 'svw' | 'lvw' | 'dvw' | 'vh' | 'svh' | 'lvh' | 'dvh' | 'vi' | 'svi' | 'lvi' | 'dvi' | 'vb' | 'svb' | 'lvb' | 'dvb' | 'vmin' | 'svmin' | 'lvmin' | 'dvmin' | 'vmax' | 'svmax' | 'lvmax' | 'dvmax'
baseValue?: {
rem?: number
}
applyTo?: SDTFQuery,
};
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "To TypeScript",
"parsers": [
{
"name": "to-typescript",
"output": {
"type": "file",
"filePath": "tokens.ts"
}
}
]
}
]
}/**
* @enum {string} All the valid paths for the collection colors.
* Use it when calling `getColorsTokenByMode`
*/
export const colorsColorPath = {
'colors.Core.blue-100': 'colors.Core.blue-100',
'colors.Core.blue-700': 'colors.Core.blue-700',
'colors.semantic.background.button.primary.hover': 'colors.semantic.background.button.primary.hover'
} as const;
export type colorsColorPathType = keyof typeof colorsColorPath;
export type colorsPathType = colorsColorPathType;
/**
* All the modes of the collection colors.
* Use it when calling `getColorsTokenByMode`
*/
export const colorsModes = [ 'light', 'dark' ] as const;
export type colorsModesType = typeof colorsModes[number];
/**
* All the tokens of the collection colors.
* Use `getColorsTokenByMode` to retrieve the tokens
*/
export const colors = {
'colors.Core.blue-100': { dark: 'rgb(229, 29, 29)', light: 'rgb(255, 255, 255)' },
'colors.Core.blue-700': { dark: 'rgb(229, 0, 0)', light: 'rgb(255, 200, 255)' },
'colors.semantic.background.button.primary.hover': { dark: 'rgb(229, 29, 29)', light: 'rgb(255, 200, 255)' }
} as const;
/**
* Retrieve a token for the collection 'colors'.
* @param {keyof typeof colorsPath} path - The path to the token
* @param {'light' | 'dark'} mode - The mode of the token you want to retrieve
* @returns {number | string} The value of a token for a given mode
*/
export function getColorsTokenByMode<T extends colorsPathType, M extends keyof typeof colors[T]>(path: T, mode: M) {
if (!colors[path]) {
throw new Error("Path: '" + path + "' doesn't exist for collection 'colors'. Here are all the valid paths for each type:" + `
- color:
- colors.Core.blue-100
- colors.Core.blue-700
- colors.semantic.background.button.primary.hover`)
}
if (!colors[path][mode]) {
throw new Error("Invalid mode '" + mode.toString() + "' for collection 'colors' at path '" + path + "', here are all the valid modes:\n- " + Object.keys(colors[path]).join('\n- '))
}
return colors[path][mode]
}interface parser {
name: 'to-typescript';
output: {
type: 'file';
filePath: string;
};
options?: {
moduleExport?: 'es6' | 'commonjs';
};
}{1stLevelGroupName? | mode? | base}.json{ collection: {type: {mode: { groupName: { tokenName: ... }}}}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"Core": {
"blue-100": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
}
},
"$description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
}
},
"$description": "token 2 aliased with n modes within collection within n groups"
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.Core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.Core.blue-700"
}
},
"$description": "alias token with n modes within collection within n groups"
}
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens in JSON",
"parsers": [
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "output/tokens.json"
}
}
]
}
]
}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"Core": {
"blue-100": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
}
},
"$description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
}
},
"$description": "token 2 aliased with n modes within collection within n groups"
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.Core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.Core.blue-700"
}
},
"$description": "alias token with n modes within collection within n groups"
}
}
}
}
}
}
}| '%'
| 'px'
| 'em'
| 'rem'
| 'pt'
| 'pc'
| 'in'
| 'cm'
| 'mm'
| 'ex'
| 'cap'
| 'ch'
| 'ic'
| 'lh'
| 'rlh'
| 'vw'
| 'svw'
| 'lvw'
| 'dvw'
| 'vh'
| 'svh'
| 'lvh'
| 'dvh'
| 'vi'
| 'svi'
| 'lvi'
| 'dvi'
| 'vb'
| 'svb'
| 'lvb'
| 'dvb'
| 'vmin'
| 'svmin'
| 'lvmin'
| 'dvmin'
| 'vmax'
| 'svmax'
| 'lvmax'
| 'dvmax'{ rem: number }| { collection: string | true }
| { group: string | true }
| { token: string | true }
| SDTFQuery{ token: true }curl -X POST 'https://api.specifyapp.com/v2/@acme-inc/repository/all-design-data/execute-rule' \
--header 'Authorization: <your-personal-access-token>' \
--header 'Content-Type: application/json' \
--data '{
"name": "SDTF",
"parsers": [
{
"name": "as-is",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}'In this guide, you’ll learn how to sync your Figma Variables and/or Styles to a Specify Repository and how to keep them updated.
Type Query = { where: Where | Array<Where> }type WhereToken = {
token:
| string
| {
name?: string;
description?: string?;
}
select:
| true
| {
token?: boolean;
parents?:
| true
| {
groups?: true;
collections?: true;
}
}
}type WhereGroup = {
group: string;
select:
| true
| {
group?: boolean;
parents?:
| true
| {
groups?: true;
collections?: true;
}
children:
| true
| {
groups?: true;
collections?: true;
tokens?: true;
}
}
}type WhereCollection = {
collection: string;
select:
| true
| {
collection?: boolean;
parents?:
| true
| {
groups?: true;
}
children:
| true
| {
groups?: true;
tokens?: true;
}
}
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get tokens from collection named 'Colors'",
"parsers": [
{
"name": "filter",
"options": {
"query": {
"where": {
"collection": "^Colors$",
"select": {
"parents": true,
"children": true
}
}
}
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get tokens from all collections whose names contain 'colors'",
"parsers": [
{
"name": "filter",
"options": {
"where": {
"collection": "colors",
"select": {
"collection": true,
"children": {
"tokens": true
}
}
}
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get tokens from all groups named 'brand'",
"parsers": [
{
"name": "filter",
"options": {
"query": {
"where": {
"group": "^brand$",
"select": {
"parents": true,
"children": true
}
}
}
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get color tokens from the 'Android' collection",
"parsers": [
{
"name": "filter",
"options": {
"where": {
"collection": "^Android$",
"andWhere": {
"token": ".*",
"withTypes": { "include": ["color"] },
"select": {
"token": true,
"parents": {
"collections": true
}
}
}
}
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get color tokens from the 'Android' collection and from all groups named 'components'",
"parsers": [
{
"name": "filter",
"options": {
"where": {
"collection": "^Android$",
"andWhere": {
"group": "^components$",
"andWhere": {
"token": ".*",
"withTypes": {
"include": ["color"]
},
"select": {
"token": true,
"parents": true
}
}
}
}
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Get tokens from the group named 'Components' and/or from the group named 'Semantic'",
"parsers": [
{
"name": "filter",
"options": {
"where": {
"collection": "^Android$",
"andWhere": {
"group": "^Components$|^Semantic$",
"andWhere": {
"token": ".*",
"select": {
"token": true,
"parents": true
}
}
}
}
}
}
]
}
]
}{
"colors": {
"$collection": {
"$modes": ["light", "dark"]
},
"info": {
"infoToken": {
"$type": "color",
"$value": {
"light": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
},
"dark": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
}
}
}
},
"danger": {
"dangerToken": {
"$type": "color",
"$value": {
"light": {
"model": "rgb",
"red": 209,
"green": 204,
"blue": 204,
"alpha": 1
},
"dark": {
"model": "rgb",
"red": 19,
"green": 34,
"blue": 54,
"alpha": 1
}
}
}
}
}
}interface parser {
name: 'filter';
options: {
query: SDTFQuery;
resolveAliases?: boolean;
allowUnresolvableAliases?: boolean;
deduplicate: true | undefined;
failOnMutate: true | undefined;
};
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Only get tokens from a group named 'info' and gererate tokens in JSON",
"parsers": [
{
"name": "filter",
"options": {
"query": {
"where": {
"group": "info",
"select": {
"parents": true,
"children": true
}
}
}
}
},
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}
]
}{
"colors": {
"$collection": {
"$modes": ["light", "dark"]
},
"info": {
"infoToken": {
"$type": "color",
"$value": {
"light": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
},
"dark": {
"model": "rgb",
"red": 219,
"green": 234,
"blue": 254,
"alpha": 1
}
}
}
}
}
}


{
"colors": {
{
"colors": {
In this guide you’ll learn how to sync your design tokens from Tokens Studio to your Specify repository and how to keep them updated.
We provide the first Design Data Platform allowing you to send your design tokens and assets across your design system tools. Specify is built with this idea: configure once, synchronize anytime.
{
"Colors": {
"$collection": { "$modes": ["Light", "Dark"] },
"Core": {
"blue 100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
},
"Dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
}
}
},
"blue 700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
},
"Dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"Dark": {
"$mode": "dark",
"$alias": "Colors.Core.blue 100"
},
"Light": {
"$mode": "light",
"$alias": "Colors.Core.blue 700"
}
}
}
}
}
}
}
}
}interface parser {
name: 'change-case';
options: {
change?: 'name' | 'modes';
toCase:
| 'camelCase'
| 'capitalCase'
| 'constantCase'
| 'kebabCase'
| 'noCase'
| 'pascalCase'
| 'pascalSnakeCase'
| 'pathCase'
| 'sentenceCase'
| 'snakeCase'
| 'trainCase';
applyTo:
| { collection: string | true }
| { group: string | true }
| { token: string | true }
| SDTFQuery;
};
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "To React Native theme",
"parsers": [
{
"name": "to-react-native",
"output": {
"type": "file",
"filePath": "public/theme.js"
}
}
]
}
]
}/**
* @typedef {'primitive.spacing.1'} DimensionPath - All the valid paths for the tokens of type dimension.
* To use this type you can do: `@type {import('path/to/myTokensFile').DimensionPath}`
*/
/**
* @typedef {'themedColor.highEmphasis'} ColorPath - All the valid paths for the tokens of type color.
* To use this type you can do: `@type {import('path/to/myTokensFile').ColorPath}`
*/
/**
* @typedef {DimensionPath | ColorPath} AllPath - All possible paths
*/
/**
* @typedef {typeof pathsByType} PathsByType - All the paths for a given token type. Needed for `getTokensByType`
*/
const pathsByType = /** @type {const} */ ({
dimension: [ 'primitive.spacing.1' ],
color: [ 'themedColor.highEmphasis' ]
});
/**
* @typedef {typeof colorModes[number]} ColorModes - All the valid modes of color.
* To use this type you can do: `@type {import('path/to/myTokensFile').ColorModes}`
*/
export const colorModes = /** @type {const} */ ([ 'dark', 'light' ]);
/**
* @typedef {typeof themedColorModes[number]} ThemedcolorModes - All the valid modes of themedColor.
* To use this type you can do: `@type {import('path/to/myTokensFile').ThemedcolorModes}`
*/
export const themedColorModes = /** @type {const} */ ([ 'light', 'dark' ]);
/**
@typedef {ColorModes | ThemedcolorModes} AllMode - All the available modes
*/
/**
* @typedef {typeof tokens} Tokens - All the tokens.
* Use `getTokenByMode` to retrieve one.
*/
export const tokens = /** @type {const} */ ({
'primitive.spacing.1': '4px',
'themedColor.highEmphasis': { dark: '#ffffff', light: '#000000' }
});
/**
* Retrieve any token for a given mode. If available, the default mode will be: 'default'
* @template {AllPath} Path - A generic extending all the possible paths
* @template {Tokens[Path] extends Record<string, any>
? keyof Tokens[Path]
: undefined} Mode - A generic representing all the valid modes for a given path
* @template {Tokens[Path] extends Record<string, any>
? Tokens[Path][Mode extends undefined ? never : Mode]
: Tokens[Path]} Return - The return type
* @param {Path} path - The path to the token
* @param {Mode} mode - The mode of the token you want to retrieve
* @returns {Return} - The value of a token for a given mode
*/
export function getTokenByMode(path, mode) {
if (!tokens[path]) {
throw new Error("Path: '" + path + "' doesn't exist. Here are all the valid paths:\n- " + Object.keys(tokens).join('\n- '))
}
if (typeof tokens[path] !== 'object') {
return tokens[path] ;
}
if (!mode) throw new Error('Mode is undefined but it should be one of ' + Object.keys(tokens[path]).join(', ') + ' for path: ' + path);
if (!tokens[path][mode]) {
throw new Error("Invalid mode '" + mode.toString() + " at path '" + path + "', here are all the valid modes:\n- " + Object.keys(tokens[path]).join('\n- '))
}
return tokens[path][mode]
}
/**
* Retrieve all the tokens for a specific type (color, dimension, etc...).
* Note that the value will either be a string or an object if the token has modes
* @template {keyof PathsByType} Type - A generic extending all the possible types
* @template {Tokens[PathsByType[Type][number]]} Token - A generic representing a union of all the outputs
* @param {Type} type - The path to the token
* @returns {Array<Token>} - An array with all the values
*/
export function getTokensByType(type) {
if (!pathsByType[type]) {
throw new Error('The type: \'' + type + '\' does not exist')
}
return pathsByType[type].map(path => tokens[path]);
}interface parser {
name: 'to-react-native';
output: {
type: 'file';
filePath: string;
};
options?: {
typescript?: boolean;
moduleExport?: 'es6' | 'commonjs';
};
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "To JavaScript",
"parsers": [
{
"name": "to-javascript",
"output": {
"type": "file",
"filePath": "tokens.js"
}
}
]
}
]
}/**
* @enum {string} All the valid paths for the collection colors.
* Use it when calling `getColorsTokenByMode`
*/
export const colorsColorPath = {
'colors.Core.blue-100': 'colors.Core.blue-100',
'colors.Core.blue-700': 'colors.Core.blue-700',
'colors.semantic.background.button.primary.hover': 'colors.semantic.background.button.primary.hover'
};
/**
* All the modes of the collection colors.
* Use it when calling `getColorsTokenByMode`
*/
export const colorsModes = [ 'light', 'dark' ];
/**
* All the tokens of the collection colors.
* Use `getColorsTokenByMode` to retrieve the tokens
*/
export const colors = {
'colors.Core.blue-100': { dark: 'rgb(229, 29, 29)', light: 'rgb(255, 255, 255)' },
'colors.Core.blue-700': { dark: 'rgb(229, 0, 0)', light: 'rgb(255, 200, 255)' },
'colors.semantic.background.button.primary.hover': { dark: 'rgb(229, 29, 29)', light: 'rgb(255, 200, 255)' }
};
/**
* Retrieve a token for the collection 'colors'.
* @param {keyof typeof colorsPath} path - The path to the token
* @param {'light' | 'dark'} mode - The mode of the token you want to retrieve
* @returns {number | string} The value of a token for a given mode
*/
export function getColorsTokenByMode(path, mode) {
if (!colors[path]) {
throw new Error("Path: '" + path + "' doesn't exist for collection 'colors'. Here are all the valid paths for each type:" + `
- color:
- colors.Core.blue-100
- colors.Core.blue-700
- colors.semantic.background.button.primary.hover`)
}
if (!colors[path][mode]) {
throw new Error("Invalid mode '" + mode.toString() + "' for collection 'colors' at path '" + path + "', here are all the valid modes:\n- " + Object.keys(colors[path]).join('\n- '))
}
return colors[path][mode]
}interface parser {
name: 'to-javascript';
output: {
type: 'file';
filePath: string;
};
options?: {
typescript?: boolean;
moduleExport?: 'es6' | 'commonjs';
};
}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"aliases": {
"border": {
"active": {
"$type": "color",
"$value": {
"dark": {
"$alias": "colors.core.label.blue-base",
"$mode": "dark"
},
"light": {
"$alias": "colors.core.label.blue-base",
"$mode": "light"
}
}
}
}
},
"core": {
"label": {
"blue-base": {
"$type": "color",
"$value": {
"dark": {
"model": "rgb",
"red": 96,
"green": 168,
"blue": 250,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 17,
"green": 125,
"blue": 249,
"alpha": 1
}
}
},
"blue-lighter": {
"$type": "color",
"$value": {
"dark": {
"model": "rgb",
"red": 41,
"green": 52,
"blue": 67,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 219,
"green": 236,
"blue": 254,
"alpha": 1
}
}
}
}
}
},
"dimensions": {
"$collection": {
"$modes": [
"desktop",
"mobile"
]
},
"base": {
"dimension-01": {
"$type": "dimension",
"$value": {
"mobile": {
"value": 2,
"unit": "px"
},
"desktop": {
"value": 4,
"unit": "px"
}
}
},
"dimension-02": {
"$type": "dimension",
"$value": {
"mobile": {
"value": 4,
"unit": "px"
},
"desktop": {
"value": 8,
"unit": "px"
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Format all token names and modes to kebabCase and generate tokens in JSON",
"parsers": [
{
"name": "change-case",
"options": {
"change": "names",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "change-case",
"options": {
"change": "modes",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}
]
}{
"colors": {
"$collection": { "$modes": ["light", "dark"] },
"core": {
"blue-100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
},
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
}
}
},
"blue-700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
},
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.core.blue-700"
}
}
}
}
}
}
}
}
}'names' | 'modes'| 'camelCase'
| 'capitalCase'
| 'constantCase'
| 'kebabCase'
| 'noCase'
| 'pascalCase'
| 'pascalSnakeCase'
| 'pathCase'
| 'sentenceCase'
| 'snakeCase'
| 'trainCase'| { collection: string | true }
| { group: string | true }
| { token: string | true }
| SDTFQuery{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens as a Tailwind theme",
"parsers": [
{
"name": "to-tailwind",
"output": {
"type": "file",
"filePath": "theme.js"
}
}
]
}
]
}/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
colors: {
colors: {
core: {
label: {
'blue-lighter': {
'dark': 'rgb(41, 52, 67)',
'light': 'rgb(219, 236, 254)'
},
'blue-base': {
'dark': 'rgb(96, 168, 250)',
'light': 'rgb(17, 125, 249)'
}
}
},
aliases: {
border: {
active: {
'dark': 'rgb(98, 77, 227)',
'light': 'rgb(235, 33, 33)'
}
}
}
}
},
spacing: {
'dimensions-base-dimension-01-desktop': '4px',
'dimensions-base-dimension-01-mobile': '2px',
'dimensions-base-dimension-02-desktop': '8px',
'dimensions-base-dimension-02-mobile': '4px'
}
}
}
}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"aliases": {
"border": {
"active": {
"$type": "color",
"$value": {
"dark": {
"$alias": "colors.core.label.blue-base",
"$mode": "dark"
},
"light": {
"$alias": "colors.core.label.blue-base",
"$mode": "light"
}
}
}
}
},
"core": {
"label": {
"blue-base": {
"$type": "color",
"$value": {
"dark": {
"model": "rgb",
"red": 96,
"green": 168,
"blue": 250,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 17,
"green": 125,
"blue": 249,
"alpha": 1
}
}
},
"blue-lighter": {
"$type": "color",
"$value": {
"dark": {
"model": "rgb",
"red": 41,
"green": 52,
"blue": 67,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 219,
"green": 236,
"blue": 254,
"alpha": 1
}
}
}
}
}
},
"dimensions": {
"$collection": {
"$modes": [
"desktop",
"mobile"
]
},
"base": {
"dimension-01": {
"$type": "dimension",
"$value": {
"mobile": {
"value": 2,
"unit": "px"
},
"desktop": {
"value": 4,
"unit": "px"
}
}
},
"dimension-02": {
"$type": "dimension",
"$value": {
"mobile": {
"value": 4,
"unit": "px"
},
"desktop": {
"value": 8,
"unit": "px"
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Generate tokens as a Tailwind theme",
"parsers": [
{
"name": "to-tailwind",
"output": {
"type": "file",
"filePath": "theme.js"
},
"options": {
"useCssVariable": true,
"cssVariableTemplate": {
"tokenNameTemplate": "--{{groups}}-{{token}}"
}
}
}
]
}
]
}/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
colors: {
colors: {
core: {
label: {
'blue-base': {
dark: 'var(--core-label-blue-base)',
light: 'var(--core-label-blue-base)'
},
'blue-lighter': {
dark: 'var(--core-label-blue-lighter)',
light: 'var(--core-label-blue-lighter)'
}
}
},
aliases: {
border: {
active: {
dark: 'var(--aliases-border-active)',
light: 'var(--aliases-border-active)'
}
}
}
}
},
spacing: {
'dimensions-base-dimension-01-desktop': 'var(--base-dimension-01)',
'dimensions-base-dimension-01-mobile': 'var(--base-dimension-01)',
'dimensions-base-dimension-02-desktop': 'var(--base-dimension-02)',
'dimensions-base-dimension-02-mobile': 'var(--base-dimension-02)'
}
}
}
}interface parser {
name: 'to-tailwind';
output: {
type: 'file';
filePath: string; // e.g theme.js
};
options?: {
useCssVariable?: boolean;
cssVariableTemplate?: {
tokenNameTemplate?: string;
tokenNotInCollectionNameTemplate?: string;
}
};
}name to your source






type FileOutput = {
type: 'file';
filePath: string;
}type DirectoryOutput = {
type: 'directory';
directoryPath: string;
}"parsers": [
{
"name": "to-css-custom-properties",
"output": {
"type": "file",
"filePath": "style.css"
}
}
// ...
]interface parser {
name: 'to-json';
output: {
type: 'file';
filePath: string;
};
options?: {
output?: 'raw' | 'css';
};
}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"Core": {
"blue-100": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
}
},
"$description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
}
},
"$description": "token 2 aliased with n modes within collection within n groups"
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.Core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.Core.blue-700"
}
},
"$description": "alias token with n modes within collection within n groups"
}
}
}
}
}
}
}rules lets you transform tokens by chaining parsers{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "To JSON",
"parsers": [
{
"name": "to-json",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}
]
}{
"colors": {
"Core": {
"blue-100": {
"dark": {
"model": "rgb",
"red": 229,
"green": 29,
"blue": 29,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 255,
"green": 255,
"blue": 255,
"alpha": 1
}
},
"blue-700": {
"dark": {
"model": "rgb",
"red": 229,
"green": 0,
"blue": 0,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 255,
"green": 200,
"blue": 255,
"alpha": 1
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"dark": {
"model": "rgb",
"red": 229,
"green": 29,
"blue": 29,
"alpha": 1
},
"light": {
"model": "rgb",
"red": 255,
"green": 200,
"blue": 255,
"alpha": 1
}
}
}
}
}
}
}
}{
"colors": {
"$collection": {
"$modes": [
"light",
"dark"
]
},
"Core": {
"blue-100": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 29,
"alpha": 1,
"green": 29,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 255,
"model": "rgb"
}
},
"$description": "token 1 aliased with n modes within collection within n groups"
},
"blue-700": {
"$type": "color",
"$value": {
"dark": {
"red": 229,
"blue": 0,
"alpha": 1,
"green": 0,
"model": "rgb"
},
"light": {
"red": 255,
"blue": 255,
"alpha": 1,
"green": 200,
"model": "rgb"
}
},
"$description": "token 2 aliased with n modes within collection within n groups"
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.Core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.Core.blue-700"
}
},
"$description": "alias token with n modes within collection within n groups"
}
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "To JSON",
"parsers": [
{
"name": "to-json",
"output": {
"type": "file",
"filePath": "tokens.json"
},
"options": {
"output": "css"
}
}
]
}
]
}{
"colors": {
"Core": {
"blue-100": {
"dark": "rgb(229, 29, 29)",
"light": "rgb(255, 255, 255)"
},
"blue-700": {
"dark": "rgb(229, 0, 0)",
"light": "rgb(255, 200, 255)"
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"dark": "rgb(229, 29, 29)",
"light": "rgb(255, 200, 255)"
}
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "css",
"parsers": [
{
"name": "filter",
"options": {
"query": {
"where": {
"collection": "Colors",
"select": {
"parents": true,
"children": true
}
}
}
}
},
{
"name": "convert-color",
"options": {
"toFormat": "hsl",
"applyTo": {
"collection": true
}
}
},
{
"name": "change-case",
"options": {
"change": "names",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "change-case",
"options": {
"change": "modes",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "to-css-custom-properties",
"output": {
"type": "file",
"filePath": "tokens.css"
}
}
]
}
]
}{
"version": "2",
"repository": "@organization/repository",
"rules": [
{
"name": "css",
"parsers": [
{
"name": "filter",
"options": {
"query": {
"where": {
"collection": "Colors",
"select": {
"parents": true,
"children": true
}
}
}
}
},
{
"name": "convert-color",
"options": {
"toFormat": "hsl",
"applyTo": {
"collection": true
}
}
},
{
"name": "change-case",
"options": {
"change": "names",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "change-case",
"options": {
"change": "modes",
"toCase": "kebabCase",
"applyTo": {
"collection": true
}
}
},
{
"name": "to-css-custom-properties",
"output": {
"type": "file",
"filePath": "tokens.css"
}
}
]
}
]
}
Parsers are functions allowing you to transform design tokens and assets coming from Specify to fit your needs and company standards.


Learn more about how to configure Specify to generate design tokens and assets fitting your company standards.
{
"Colors": {
"$collection": { "$modes": ["Light", "Dark"] },
"Core": {
"blue 100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 219,
"blue": 254,
"alpha": 1,
"green": 236,
"model": "rgb"
},
"Dark": {
"red": 41,
"blue": 67,
"alpha": 1,
"green": 52,
"model": "rgb"
}
}
},
"blue 700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"Light": {
"red": 17,
"blue": 249,
"alpha": 1,
"green": 125,
"model": "rgb"
},
"Dark": {
"red": 96,
"blue": 250,
"alpha": 1,
"green": 168,
"model": "rgb"
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"Dark": {
"$mode": "dark",
"$alias": "Colors.Core.blue 100"
},
"Light": {
"$mode": "light",
"$alias": "Colors.Core.blue 700"
}
}
}
}
}
}
}
}
}{
"version": "2",
"repository": "@organization/repository",
// Only use the personalAccessToken when working with the CLI
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Convert colors in HSL and generate tokens in JSON",
"parsers": [
{
"name": "convert-color",
"options": {
"toFormat": "hsl"
}
},
{
"name": "to-sdtf",
"output": {
"type": "file",
"filePath": "tokens.json"
}
}
]
}
]
}{
"colors": {
"$collection": { "$modes": ["light", "dark"] },
"core": {
"blue-100": {
"$type": "color",
"$description": "token 1 aliased with n modes within collection within n groups",
"$value": {
"light": {
"model": "hsl",
"hue": 211,
"saturation": 95,
"lightness": 93,
"alpha": 1
},
"dark": {
"model": "hsl",
"hue": 215,
"saturation": 24,
"lightness": 21,
"alpha": 1
}
}
},
"blue-700": {
"$type": "color",
"$description": "token 2 aliased with n modes within collection within n groups",
"$value": {
"light": {
"model": "hsl",
"hue": 212,
"saturation": 95,
"lightness": 52,
"alpha": 1
},
"dark": {
"model": "hsl",
"hue": 212,
"saturation": 94,
"lightness": 68,
"alpha": 1
}
}
}
},
"semantic": {
"background": {
"button": {
"primary": {
"hover": {
"$type": "color",
"$description": "alias token with n modes within collection within n groups",
"$value": {
"dark": {
"$mode": "dark",
"$alias": "colors.core.blue-100"
},
"light": {
"$mode": "light",
"$alias": "colors.core.blue-700"
}
}
}
}
}
}
}
}
}interface parser {
name: 'convert-color';
options: {
toFormat:
| 'hex'
| 'rgb'
| 'hsl'
| 'hsb'
| 'lch'
| 'lab';
applyTo?:
| { collection: string | true }
| { group: string | true }
| { token: string | true }
| SDTFQuery;
};
}| 'hex'
| 'rgb'
| 'hsl'
| 'hsb'
| 'lch'
| 'lab'| { collection: string | true }
| { group: string | true }
| { token: string | true }
| SDTFQuery{ token: true }
Types define every type of design token and asset Specify is compatible with. Use them to target specific types of design data you want to pull from Specify and manage with rules and parsers.
module.exports = {
repository: '@acme-inc/all-design-data',
personalAccessToken: '<your-personal-access-token>',
rules: [],
};{
"repository": "@acme-inc/all-design-data",
"personalAccessToken": "<your-personal-access-token>",
"rules": []
}module.exports = {
repository: '@workspace/repository',
personalAccessToken: '<your-personal-access-token>',
rules: [],
};{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": []
}interface Rule {
name: string;
path: string;
filter?: {
types: Array<TokenType>
};
parsers?: Array<Parser>;
};interface Parser {
name: string;
options?: Record<string, any>;
}Record<string, any>[
{
name: 'Design Tokens',
path: 'styles/design-tokens.css',
filter: {
types: ['color', 'measurement']
},
parsers: [
{
name: 'sort-by',
options: {
keys: ['name']
}
},
{
name: 'to-css-custom-properties'
}
]
},
][
{
"name": "Design Tokens",
"path": "styles/design-tokens.css",
"filter": {
"types": ["color", "measurement"]
},
"parsers": [
{
"name": "sort-by",
"options": {
"keys": ["name"]
}
},
{
"name": "to-css-custom-properties"
}
]
}
]{
"repository": "@acme-inc/all-design-data",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "All design tokens in JSON",
"path": "design-tokens.json",
"parsers": []
}
]
}module.exports = {
repository: '@acme-inc/all-design-data',
personalAccessToken: '<your-personal-access-token>',
rules: [
{
name: 'All design tokens in JSON',
path: 'design-tokens.json',
parsers: [],
},
],
};{
"id": String,
"createdAt": String,
"updatedAt": String,
"name": String,
"value": Object,
"meta": Object,
"type": String,
"originId": String,
"sourceId": String,
"description": String,
"repositoryId": String
}module.exports = {
repository: '@acme-inc/all-design-data',
personalAccessToken: '<your-personal-access-token>',
rules: [
{
name: 'All design tokens in JSON',
path: 'colors.css',
filter: {
types: ['color']
},
parsers: [
{
name: 'to-css-custom-properties',
options: {
formatTokens: {
color: 'hsl'
},
},
},
],
},
],
};{
"repository": "@acme-inc/all-design-data",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Colors as CSS Custom Properties",
"path": "colors.css",
"filter": {
"types": ["color"]
},
"parsers": [
{
"name": "to-css-custom-properties",
"options": {
"formatTokens": {
"color": "hsl"
}
}
}
]
}
]
}[
{
"name": "Primary/100",
"value": {
"a": 1,
"b": 254,
"g": 233,
"r": 237
},
"type": "color",
"description": ""
},
{
"name": "Primary/200",
"value": {
"a": 1,
"b": 254,
"g": 214,
"r": 221
},
"type": "color",
"description": ""
},
{
"name": "Primary/300",
"value": {
"a": 1,
"b": 253,
"g": 181,
"r": 196
},
"type": "color",
"description": ""
}
]:root {
/* COLOR */
--primary-100: hsl(251, 91%, 95%);
--primary-200: hsl(251, 95%, 92%);
--primary-300: hsl(252, 95%, 85%);
}interface BorderValue {
color: {
value: ColorValue;
};
type:
| 'none'
| 'hidden'
| 'dotted'
| 'dashed'
| 'solid'
| 'double'
| 'groove'
| 'ridge'
| 'inset'
| 'outset';
width: {
value: MeasurementValue;
};
align?: string;
radii?: MeasurementValue;
rectangleCornerRadii?: Array<MeasurementValue>;
dashes?: Array<MeasurementValue>;
}interface ColorValue {
r: number;
g: number;
b: number;
a: number;
}interface DepthValue {
depth: number;
}interface DurationValue {
duration: number;
unit: string;
}interface StepForGradient {
type: string;
color: {
value: ColorValue;
};
position: number;
}
interface Gradient {
angle: string;
colors: Array<StepForGradient>;
}
interface GradientValue {
gradients: Array<Gradient>;
}interface MeasurementValue {
measure: number;
unit?: string;
}interface OpacityValue {
opacity: number;
}type ShadowValue = Array<{
color: {
value: ColorValue;
};
offsetX: {
value: MeasurementValue;
};
offsetY: {
value: MeasurementValue;
};
blur: {
value: MeasurementValue;
};
spread?: {
value: MeasurementValue;
};
isInner: boolean;
}>;export type TextTransformValue =
| 'none'
| 'capitalize'
| 'uppercase'
| 'lowercase';
export type TextDecorationValue =
| 'none'
| 'underline'
| 'overline'
| 'line-through'
| 'dashed'
| 'wavy';
export type HorizontalAlignValue =
| 'initial'
| 'left'
| 'right'
| 'center'
| 'justify'
| 'start'
| 'end'
| 'justify-all'
| 'match-parent';
export type VerticalAlignValue =
| 'initial'
| 'baseline'
| 'sub'
| 'super'
| 'text-top'
| 'text-bottom'
| 'middle'
| 'top'
| 'bottom';
export interface TextStyleValue {
color?: {
value: ColorValue;
};
font: {
value: FontValue;
};
fontSize: {
value: MeasurementValue;
};
lineHeight?: {
value: MeasurementValue;
};
letterSpacing?: {
value: MeasurementValue;
};
textAlign?: {
horizontal?: HorizontalAlignValue;
vertical?: VerticalAlignValue;
};
textTransform?: TextTransformValue;
fontVariant?: Array<string>;
textDecoration?: Array<TextDecorationValue>;
textIndent?: {
value: MeasurementValue;
};
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Borders",
"path": "borders.json",
"filter": {
"types": [
"border"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Colors",
"path": "colors.json",
"filter": {
"types": [
"color"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / zIndex",
"path": "zIndex.json",
"filter": {
"types": [
"depth"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / durations",
"path": "durations.json",
"filter": {
"types": [
"duration"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Gradients",
"path": "gradients.json",
"filter": {
"types": [
"gradient"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Measurements",
"path": "measurements.json",
"filter": {
"types": [
"measurement"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Opacities",
"path": "opacities.json",
"filter": {
"types": [
"opacity"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Shadows",
"path": "shadows.json",
"filter": {
"types": [
"shadow"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Text Styles",
"path": "textStyles.json",
"filter": {
"types": [
"textStyle"
]
}
}
]
}interface BitmapValue {
url: string;
dimension?: number;
format?: string;
}export type Provider = 'Custom font' | 'Google Fonts';
export type FontWeightKeys = '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
export interface FontValue {
fontFamily: string;
fontPostScriptName: string;
fontWeight?: string | number;
fontFileMissing?: boolean;
isItalic?: boolean;
provider?: Provider;
url?: string;
format?: 'ttf';
}interface VectorValue {
url: string;
format: 'svg' | 'pdf';
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Images",
"path": "bitmaps.json",
"filter": {
"types": [
"bitmap"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Fonts",
"path": "fonts.json",
"filter": {
"types": [
"font"
]
}
}
]
}{
"repository": "@workspace/repository",
"personalAccessToken": "<your-personal-access-token>",
"rules": [
{
"name": "Design Tokens / Icons",
"path": "vectors.json",
"filter": {
"types": [
"vector"
]
}
}
]
}Record<'types', Array<TokenType>>