This project bridges Figma variables and the W3C Design Tokens Format by importing and exporting tokens while preserving metadata needed for real-world workflows.
- Overview
- Quickstart
- Loading the Plugin in Figma
- GitHub Integration Guide
- Import & Export Behavior
- Token Support & Limitations
- Testing & Validation
- Repository Tour
- Typical Flow
- Working With The Plugin
$extensionsMetadata
- Reads live variables from a Figma document, converts them into an intermediate token graph, and captures per-mode metadata for round-tripping back to Figma.
- Parses DTCG-compliant JSON, validates values and aliases, and normalizes them into the same intermediate representation.
- Serializes the token graph back to DTCG JSON with deterministic grouping so version-control diffs stay stable.
- Resolves aliases and validates reference graphs, warning about missing targets or cycles before data is pushed back to design tools.
- Preserves
$descriptionand$extensionsblocks (notablycom.figma) so downstream tools retain authoring context.
- Install prerequisites. Use a recent Node.js LTS release (v18+) so esbuild and the TypeScript configuration behave consistently.
- Review the Figma Plugin Quickstart. The official guide at https://developers.figma.com/docs/plugins/plugin-quickstart-guide/ outlines the broader environment setup and how Figma expects development plugins to be structured.
- Install dependencies. Run
npm installto fetch plugin, build, and test dependencies. - Build the plugin. Execute
npm run buildfor a one-off compile ornpm run watchto continuously rebuild during development. Whilenpm run watchis active you can keep the Figma desktop app pointed at the same folder and see updates after each rebuild. - Check types. Run
npm run typecheckbefore loading the plugin to confirm the core project is type-safe.
- Build first. Ensure
npm run build(or thewatchtask) has produced thedist/main.jsanddist/ui.htmlfiles that the bundledmanifest.jsonreferences. - Add as a development plugin. In the Figma desktop app, Right click in document → Plugins → Development → Import plugin from manifest… and select this repository’s
manifest.json. - Keep the folder synced. Leave the manifest pointing at this working directory so every rebuild is immediately reflected when you relaunch the plugin.
- Share with testers. Testers can repeat the same import-from-manifest flow against a local clone or zipped copy of the repository. After importing, they can run the plugin from Right click in document → Plugins → Development, even without Node.js installed.
- Network permissions. The manifest enables GitHub network access; review the allowed domains if your organization applies additional sandbox restrictions.
- Export typography tokens. Use the Export typography.json action to capture every local text style, even when no variables exist. The export leverages
src/core/typography.tsto normalize units, retain$extensions, and emit a DTCG-compliant payload. - Preview typography data. When the plugin exports typography tokens it also streams the first file back to the UI so reviewers can inspect the generated JSON without leaving Figma.
- Round-trip support. Imported typography tokens map back onto Figma text styles, honoring preserved metadata and surfacing warnings whenever unsupported units need manual intervention.
- Generate a personal access token (PAT) with
reposcope so the plugin can list repositories, enumerate branches, and write commits or pull requests. - The integration remembers your last-selected repository, branch, and folder to streamline iterative syncs.
- When exporting tokens, choose whether to commit directly to the configured branch or open a pull request without leaving Figma.
- The plugin fetches token files from the target repository; verify that the folder structure matches the expected layout before importing.
- Exports honor the active selection—current collection/mode or the entire token graph—so double-check the scope prior to pushing updates upstream.
- Importers let you filter by Figma collection, mode, or GitHub context, and remember preferred combinations for faster iteration.
- Color normalization supports hex, RGB, and other DTCG-compliant formats. Enable the Allow hex strings toggle to keep raw hex values when downstream tooling requires them.
- When exporting, toggle Style Dictionary JSON to emit
#RRGGBBcolor strings instead of W3C color objects for easier ingestion by Style Dictionary pipelines. - Enable Flatten collections during export to drop the top-level collection grouping so tokens appear as a single hierarchy rooted at their variable paths.
- Partial imports surface validation warnings yet still populate the intermediate graph so you can iterate in Figma before running a full sync.
- Exports normalize token paths and ordering to keep version-control diffs minimal when committing back to source control.
$typevalues for color, number, string, and boolean are fully supported for round-tripping between Figma and DTCG.- Aliases are maintained when the target token exists and passes validation; unresolved references are flagged before export.
- Unsupported primitives or complex alias chains are preserved in the intermediate representation when possible but may be omitted from final exports. Review plugin warnings to understand what was skipped.
The plugin follows a modular, layered architecture:
- Core Layer (
src/core/) - Framework-agnostic token graph types, color conversions, normalization helpers, and the staged pipeline logic. This layer has no dependencies on Figma or UI concerns. - Adapter Layer (
src/adapters/) - Format boundaries for DTCG and Figma, translating between raw platform data and the core intermediate representation. - Application Layer (
src/app/) - Plugin UI logic, GitHub integration, and top-level command handlers.- GitHub Handlers (
src/app/github/handlers/) - Modular, domain-specific handlers for authentication, repositories, branches, folders, commits, imports, and state management. Each handler is independently testable. - UI Components (
src/app/ui/) - Reusable UI components including autocomplete, DOM helpers, and feature modules for import, export, and resize functionality.
- GitHub Handlers (
- Unit Tests: Run
npm testto execute the Vitest test suite. Tests are located in:src/**/*.test.ts- Component and handler unit tests co-located with source filestests/__tests__/**/*.test.ts- Core functionality and integration tests
- Type Checking: Run
npm run typecheckto validate TypeScript types across the entire codebase. - Linting: Run
npm run lintto check code quality and style with ESLint. The configuration enforces TypeScript best practices and warns aboutanytypes and unused variables. - CI/CD: GitHub Actions automatically runs tests, type checking, and builds on all pull requests targeting
mainanddevelopbranches.
src/core/- Shared infrastructure independent of Figma or UI:ir.ts- Intermediate representation types for the token graphcolor.ts- Color space conversions and normalizationtypography.ts- Typography token handling and text style conversionsnormalize.ts- Path canonicalization and token normalization utilitiespipeline.ts- Staged processing pipeline for token transformations
src/adapters/- Format boundaries:dtcg-reader.ts/dtcg-writer.ts- DTCG JSON parsing and serializationfigma-reader.ts/figma-writer.ts- Figma variable and style conversions
src/app/- Plugin application logic:main.ts- Plugin entry point and command handlersui.ts- Main UI controller and message handlingmessages.ts- Type-safe message contracts between UI and plugingithub/- GitHub integration:dispatcher.ts- Routes GitHub messages to domain handlershandlers/- Modular handlers for auth, repos, branches, folders, commits, imports, and state
ui/- UI component library:dom-helpers.ts- DOM manipulation utilitiescomponents/autocomplete.ts- Reusable autocomplete componentfeatures/- Feature-specific UI modules (import, export, resize)
tests/- Automated test coverage:__tests__/- Core functionality tests (DTCG writer, color profiles, type validation)- Test fixtures for round-trip validation
- Initial Setup: Run
npm installto install dependencies. - Development Mode: Use
npm run watchto continuously rebuild the plugin as you make changes. The watch mode monitorssrc/app/and rebuilds both UI and main bundles automatically. - Type Safety: Run
npm run typecheckfrequently to catch type errors early. - Code Quality: Run
npm run lintto ensure code follows project conventions. - Testing: Run
npm testto execute the full test suite before committing changes. - Building: Run
npm run buildfor a one-time production build. - CI/CD: All pull requests automatically run tests, type checking, and builds via GitHub Actions.
- Figma variables are read into the core IR, capturing per-mode values and alias relationships.
- The pipeline normalizes paths, deduplicates nodes, and runs validation passes (alias analysis, color checks, etc.).
- Depending on user action, results are either written back to Figma, exported as DTCG JSON, or committed via the GitHub integration.
- Maintain deterministic ordering and canonical paths so exports remain stable.
- Preserve
$extensionsdata verbatim; treat it as opaque vendor metadata unless transformers explicitly need to augment it. - Prefer the helpers in
src/core/normalize.tsfor path and alias handling to avoid divergence between adapters.
The plugin round-trips metadata stored under the DTCG $extensions key to keep parity with the original Figma document. In practice this means:
- Figma-specific annotations live under the
com.figmanamespace and are written back unchanged so teams can rely on them for audit trails, component provenance, or handoff context. - Additional vendor extensions (for example,
org.example.analytics) are retained when importing and exporting tokens, allowing downstream tools to operate on the same enriched payload without rehydration steps. - When the pipeline normalizes or merges tokens,
$extensionsblocks are never merged heuristically; instead we surface conflicts to users so intent stays explicit.
If you need to evolve the metadata shape, prefer adding new keys inside the existing namespace rather than rewriting or removing fields to avoid breaking synchronization with external systems.
