figma
Skill50 starsChanged 11 months agoMITView on GitHub
Syncs design tokens between code and Figma using Variables API or Tokens Studio plugin. Use when establishing Figma-to-code workflows, exporting Figma tokens, or setting up design-development handoff.
- Reads credentials
- Sends data out
52 other projects use a version of this.
Adopted by
Most recently taken up by
- JustinWangJP/cc-agent-teams-action-monitortheir own version, first seen Nov 8, 2026
- skyfox675/agents-skillstheir own version, first seen Nov 6, 2026
- edenfunf/reelmimictheir own version, first seen Nov 4, 2026
- Shanksg/clawskillstheir own version, first seen Nov 1, 2026
- SFKislev/Fluetheir own version, first seen Nov 1, 2026
- getsentry/juniortheir own version, first seen Nov 1, 2026
Used with
Projects with it also use analytics-metrics, aws-account-management and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
hoodiniSkillanalytics-metrics
Build data visualization and analytics dashboards. Use when creating charts, KPI displays, metrics dashboards, or data visualization components. Triggers on analytics, dashboard, charts, metrics, KPI, data visualization, Recharts.
Also in 3 projects that use this
hoodiniSkillaws-account-management
Manage AWS accounts, organizations, IAM, and billing. Use when setting up AWS Organizations, managing IAM policies, controlling costs, or implementing multi-account strategies. Triggers on AWS Organizations, AWS IAM, AWS billing, Cost Explorer, SCPs, multi-account, AWS SSO, Identity Center.
Also in 3 projects that use this
LangChainSkillslideshow
Author a HyperFrames slideshow — a presentation, pitch deck, or interactive deck with discrete slides, fragment reveals, branching, hotspot navigation, and built-in presenter mode with speaker notes; also converts an existing page into a deck. Output is a navigable deck, not a rendered MP4. If the user didn't explicitly ask for a slideshow, confirm before authoring. Unclear → /hyperframes.
Also in 8 projects that use this
jaron-goh-centrSkilltalking-head-recut
Package an existing talking-head / interview / podcast video with timed, designed GRAPHIC OVERLAY cards — kinetic titles, lower-thirds, data callouts, quotes, side panels, picture-in-picture — synced to the transcript, on a 16:9 / 9:16 / 4:5 canvas of your choice; the clip plays untouched underneath. Trigger on "graphic overlays", "on-screen graphics", "package / dress up my video". Not plain subtitles (/embedded-captions). Unclear → /hyperframes.
Also in 6 projects that use this
LangChainSkillfaceless-explainer
Turn arbitrary text — an article, notes, a topic, a brief — into a faceless explainer video: there is no site or footage to capture, so the visuals are invented per scene (typography, abstract graphics, diagrams, data-viz). Use for topic explainers, concept breakdowns, how-tos, listicles. Not a video built from a website (/product-launch-video — promo or tour). Unclear → /hyperframes.
Also in 6 projects that use this
ElyzeSolutionsSkillcaptions-overlay
Overlay doctrine for the embedded-captions workflow — the caption MODEL (drop / rail / embed) and the rule that captions are an OVERLAY composited on top of the film, never a reserved bottom band you shift content up to avoid. Load when adding captions/subtitles to a talking-head or launch video, when deciding whether a phrase should be dropped, ride the verbatim rail, or be promoted to a scarce embedded climax, when laying out a composition that will carry captions (do NOT reserve a keep-out band), or when centering a composition on the true frame center under captions. Quotes the rail+embed model from embedded-captions and constraint #13 (captions overlay, keep-out band retired) from the product-launch-video scene agent. Applies ON TOP of embedded-captions.
Also in 3 projects that use this
- +4 more from hoodini
Other versions52 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 52
- heygen-com/hyperframes★ 81ksame name
- openai/skills★ 27ksame name
- edenfunf/reelmimic★ 1.8ksame name
- epam/ai-dial-chat★ 501same name
- getsentry/junior★ 409same name
- JetBrains/skills★ 386same name
- hoodini/ai-agents-skills★ 295same name
- SFKislev/Flue★ 102same name
- spmtitsolution/OpenBA-Kit★ 38same name
- STARDUSTLC666/dsh-hyperframes★ 30same name
42 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository29 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- aria-patternsSkill
- color-contrastSkill
- focus-statesSkill
- component-docsSkill
- token-docsSkill
- angularSkill
- reactSkill
- svelteSkill
- vueSkill
- getting-startedSkill
- animation-principlesSkill
- compound-componentsSkill
- dark-modeSkill
- icon-systemSkill
- layout-primitivesSkill
- breakpointsSkill
- color-scaleSkill
- design-tokens-structureSkill
- motion-scaleSkill
- radius-scaleSkill
- responsive-typographySkill
- shadow-scaleSkill
- spacing-scaleSkill
- type-scaleSkill
- z-index-scaleSkill
- framerSkill
- storybookSkill
- style-dictionarySkill
The file
We split this skill into the rules it gives an agent
2 rules. 0 are common, 2 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 44 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 481
Semantic tokens: Use aliases for theme-aware values
- Distinctive: line 482
Documentation: Keep a mapping document for designers
“Common” is measured: kept by at least 6 in 10 of the 44 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Figma Token Integration
Overview
Sync design tokens between code and Figma using Figma Variables, the Tokens Studio plugin, or Style Dictionary. Establish a single source of truth workflow for design-to-code handoff.
When to Use
- Setting up Figma Variables from code tokens
- Exporting Figma styles to code tokens
- Establishing a design token workflow
- Syncing colors, typography, and spacing with Figma
Quick Reference: Figma Token Types
| Figma Type | Maps To | Example |
| Color Variable | --color-* | --color-primary-500 |
| Number Variable | --spacing-*, --radius-* | --spacing-md |
| String Variable | Font family, mode names | --font-sans |
| Boolean Variable | Feature flags | Theme mode toggles |
The Process
- Choose workflow direction:
- Code → Figma (tokens are source of truth in code)
- Figma → Code (designers own tokens in Figma)
- Bidirectional (sync both ways)
- Select tooling: Native Variables, Tokens Studio, or custom
- Define token structure: Categories, naming, modes
- Set up sync mechanism: Plugin, API, or manual
- Document workflow: Who updates what, when to sync
Workflow Options
| Approach | Best For | Tools |
| Figma Variables (native) | Simple setups, color/number tokens | Figma UI, REST API |
| Tokens Studio | Complex tokens, multi-file | Tokens Studio plugin + GitHub |
| Style Dictionary | Enterprise, CI/CD integration | Style Dictionary + Figma API |
| Manual sync | Small teams, infrequent changes | Copy/paste with conventions |
Figma Variables (Native)
Creating Variables from Code Tokens
Token structure for Figma:
{
"color": {
"primary": {
"50": { "value": "#eff6ff", "type": "color" },
"100": { "value": "#dbeafe", "type": "color" },
"500": { "value": "#3b82f6", "type": "color" },
"900": { "value": "#1e3a8a", "type": "color" }
},
"gray": {
"50": { "value": "#f9fafb", "type": "color" },
"900": { "value": "#111827", "type": "color" }
}
},
"spacing": {
"xs": { "value": 4, "type": "number" },
"sm": { "value": 8, "type": "number" },
"md": { "value": 16, "type": "number" },
"lg": { "value": 24, "type": "number" }
},
"radius": {
"sm": { "value": 4, "type": "number" },
"md": { "value": 8, "type": "number" },
"lg": { "value": 16, "type": "number" },
"full": { "value": 9999, "type": "number" }
}
}Figma REST API Example
Create variables via API:
import Anthropic from '@anthropic-ai/sdk'; // Example using Figma API
interface FigmaVariable {
name: string;
resolvedType: 'COLOR' | 'FLOAT' | 'STRING' | 'BOOLEAN';
valuesByMode: Record<string, any>;
}
async function createFigmaVariables(
fileKey: string,
collectionName: string,
tokens: Record<string, any>
): Promise<void> {
const accessToken = process.env.FIGMA_ACCESS_TOKEN;
// Step 1: Create variable collection
const collectionResponse = await fetch(
`https://api.figma.com/v1/files/${fileKey}/variables`,
{
method: 'POST',
headers: {
'X-Figma-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
variableCollections: [
{
action: 'CREATE',
name: collectionName,
initialModeId: 'light',
},
],
}),
}
);
const { variableCollections } = await collectionResponse.json();
const collectionId = variableCollections[0].id;
// Step 2: Create variables
const variables: FigmaVariable[] = [];
for (const [category, values] of Object.entries(tokens)) {
for (const [name, token] of Object.entries(values as Record<string, any>)) {
variables.push({
name: `${category}/${name}`,
resolvedType: token.type === 'color' ? 'COLOR' : 'FLOAT',
valuesByMode: {
light: parseValue(token.value, token.type),
},
});
}
}
await fetch(`https://api.figma.com/v1/files/${fileKey}/variables`, {
method: 'POST',
headers: {
'X-Figma-Token': accessToken,
'Content-Type': 'application/json',
},
body: JSON.stringify({
variables: variables.map((v) => ({
action: 'CREATE',
variableCollectionId: collectionId,
...v,
})),
}),
});
}
function parseValue(value: string | number, type: string): any {
if (type === 'color') {
// Convert hex to Figma RGBA
const hex = value as string;
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
return { r, g, b, a: 1 };
}
return value;
}Variable Modes (Theming)
Light/dark mode setup:
{
"variableCollections": [
{
"name": "Semantic Colors",
"modes": [
{ "name": "Light", "modeId": "light" },
{ "name": "Dark", "modeId": "dark" }
]
}
],
"variables": [
{
"name": "background/default",
"valuesByMode": {
"light": { "type": "VARIABLE_ALIAS", "id": "color/gray/50" },
"dark": { "type": "VARIABLE_ALIAS", "id": "color/gray/900" }
}
},
{
"name": "text/primary",
"valuesByMode": {
"light": { "type": "VARIABLE_ALIAS", "id": "color/gray/900" },
"dark": { "type": "VARIABLE_ALIAS", "id": "color/gray/50" }
}
}
]
}Tokens Studio Integration
Token File Structure
tokens.json (Tokens Studio format):
{
"global": {
"colors": {
"primary": {
"50": { "value": "#eff6ff", "type": "color" },
"500": { "value": "#3b82f6", "type": "color" },
"900": { "value": "#1e3a8a", "type": "color" }
},
"gray": {
"50": { "value": "#f9fafb", "type": "color" },
"900": { "value": "#111827", "type": "color" }
}
},
"spacing": {
"xs": { "value": "4", "type": "spacing" },
"sm": { "value": "8", "type": "spacing" },
"md": { "value": "16", "type": "spacing" },
"lg": { "value": "24", "type": "spacing" }
},
"borderRadius": {
"sm": { "value": "4", "type": "borderRadius" },
"md": { "value": "8", "type": "borderRadius" },
"lg": { "value": "16", "type": "borderRadius" }
},
"fontFamilies": {
"sans": { "value": "Inter", "type": "fontFamilies" },
"mono": { "value": "JetBrains Mono", "type": "fontFamilies" }
},
"fontSizes": {
"xs": { "value": "12", "type": "fontSizes" },
"sm": { "value": "14", "type": "fontSizes" },
"base": { "value": "16", "type": "fontSizes" },
"lg": { "value": "18", "type": "fontSizes" }
},
"lineHeights": {
"tight": { "value": "1.25", "type": "lineHeights" },
"normal": { "value": "1.5", "type": "lineHeights" },
"relaxed": { "value": "1.75", "type": "lineHeights" }
}
},
"light": {
"bg": {
"default": { "value": "{global.colors.gray.50}", "type": "color" },
"subtle": { "value": "{global.colors.gray.100}", "type": "color" }
},
"text": {
"primary": { "value": "{global.colors.gray.900}", "type": "color" },
"secondary": { "value": "{global.colors.gray.600}", "type": "color" }
}
},
"dark": {
"bg": {
"default": { "value": "{global.colors.gray.900}", "type": "color" },
"subtle": { "value": "{global.colors.gray.800}", "type": "color" }
},
"text": {
"primary": { "value": "{global.colors.gray.50}", "type": "color" },
"secondary": { "value": "{global.colors.gray.400}", "type": "color" }
}
}
}Tokens Studio → Code Transform
Style Dictionary config (sd.config.js):
module.exports = {
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [
{
destination: 'variables.css',
format: 'css/variables',
filter: (token) => token.filePath.includes('global'),
},
{
destination: 'light.css',
format: 'css/variables',
filter: (token) => token.filePath.includes('light'),
options: {
selector: ':root, [data-theme="light"]',
},
},
{
destination: 'dark.css',
format: 'css/variables',
filter: (token) => token.filePath.includes('dark'),
options: {
selector: '[data-theme="dark"]',
},
},
],
},
tailwind: {
transformGroup: 'js',
buildPath: 'dist/',
files: [
{
destination: 'tailwind.tokens.js',
format: 'javascript/module',
},
],
},
},
};Figma Plugin Development
Plugin for Token Sync
manifest.json:
{
"name": "Token Sync",
"id": "token-sync-plugin",
"api": "1.0.0",
"main": "code.js",
"ui": "ui.html",
"editorType": ["figma"],
"networkAccess": {
"allowedDomains": ["api.github.com"]
}
}code.ts (plugin logic):
figma.showUI(__html__, { width: 400, height: 500 });
figma.ui.onmessage = async (msg) => {
if (msg.type === 'import-tokens') {
await importTokens(msg.tokens);
} else if (msg.type === 'export-tokens') {
const tokens = await exportTokens();
figma.ui.postMessage({ type: 'tokens-exported', tokens });
}
};
async function importTokens(tokens: Record<string, any>): Promise<void> {
// Get or create collection
const collections = await figma.variables.getLocalVariableCollectionsAsync();
let collection = collections.find((c) => c.name === 'Design Tokens');
if (!collection) {
collection = figma.variables.createVariableCollection('Design Tokens');
}
const modeId = collection.modes[0].modeId;
// Import each token
for (const [path, token] of flattenTokens(tokens)) {
const existing = await figma.variables.getVariableByIdAsync(
`VariableID:${path.replace(/\//g, ':')}`
);
if (existing) {
existing.setValueForMode(modeId, parseTokenValue(token));
} else {
const variable = figma.variables.createVariable(
path,
collection,
getVariableType(token.type)
);
variable.setValueForMode(modeId, parseTokenValue(token));
}
}
figma.notify(`Imported ${Object.keys(tokens).length} tokens`);
}
async function exportTokens(): Promise<Record<string, any>> {
const tokens: Record<string, any> = {};
const collections = await figma.variables.getLocalVariableCollectionsAsync();
for (const collection of collections) {
for (const variableId of collection.variableIds) {
const variable = await figma.variables.getVariableByIdAsync(variableId);
if (!variable) continue;
const path = variable.name.split('/');
let current = tokens;
for (let i = 0; i < path.length - 1; i++) {
current[path[i]] = current[path[i]] || {};
current = current[path[i]];
}
const modeId = collection.modes[0].modeId;
current[path[path.length - 1]] = {
value: formatValue(variable.valuesByMode[modeId], variable.resolvedType),
type: mapVariableType(variable.resolvedType),
};
}
}
return tokens;
}
function* flattenTokens(
obj: Record<string, any>,
path: string[] = []
): Generator<[string, any]> {
for (const [key, value] of Object.entries(obj)) {
if (value.value !== undefined) {
yield [path.concat(key).join('/'), value];
} else {
yield* flattenTokens(value, path.concat(key));
}
}
}
function getVariableType(type: string): VariableResolvedDataType {
switch (type) {
case 'color':
return 'COLOR';
case 'spacing':
case 'borderRadius':
case 'fontSizes':
return 'FLOAT';
default:
return 'STRING';
}
}
function parseTokenValue(token: { value: string; type: string }): VariableValue {
if (token.type === 'color') {
return hexToRgba(token.value);
}
if (['spacing', 'borderRadius', 'fontSizes'].includes(token.type)) {
return parseFloat(token.value);
}
return token.value;
}
function hexToRgba(hex: string): RGBA {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
return { r, g, b, a: 1 };
}Naming Conventions
| Category | Figma Convention | Code Convention |
| Colors | color/primary/500 | --color-primary-500 |
| Spacing | spacing/md | --spacing-md |
| Radius | radius/lg | --radius-lg |
| Typography | text/body/regular | --text-body |
| Shadows | shadow/md | --shadow-md |
| Semantic | bg/default | --color-bg-default |
Workflow Best Practices
- Single source of truth: Decide if code or Figma owns tokens
- Version control: Store token files in Git
- CI/CD integration: Auto-sync on merge to main
- Semantic tokens: Use aliases for theme-aware values
- Documentation: Keep a mapping document for designers
- Validation: Lint tokens before sync
Common Pitfalls
| Issue | Solution |
| Color format mismatch | Normalize to hex or RGB before sync |
| Spacing units | Use unitless in Figma, add px/rem in code |
| Missing tokens | Validate token coverage before sync |
| Mode drift | Sync all modes together, not separately |
| Name collisions | Establish naming convention upfront |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

