npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@artcom/figma-sync

v0.1.0

Published

Track drift between Figma design nodes and their code components: annotate components, hash design + code, and report sync status via snapshot or live REST backends.

Readme

figma-sync

A synchronization layer that answers "is this generated component still aligned with its Figma node?" — without being a code generator itself.

Plain ESM JavaScript, zero runtime dependencies, Node ≥ 18. Ships a figma-sync CLI plus a small library API.

Install

npm install --save-dev @artcom/figma-sync

Or, when developing against a sibling checkout:

{ "devDependencies": { "@artcom/figma-sync": "file:../figma-sync" } }

npm install then exposes the figma-sync binary (in node_modules/.bin, so it's callable from your package.json scripts) and the library entry import { loadProject } from "@artcom/figma-sync".

The tool reads/writes a .figma-sync/ directory in the current working directory (the consuming project), so run it from that project's root.

How it works

  1. Mapping — components carry a metadata comment:

    // figma-sync: file=dSRhp9PHg4w9Gnco2R19dg node=2267:1644 name=StatusCard
  2. Manifest.figma-sync/manifest.json records, per file, the design hash and code hash at generation time (update-manifest writes it). The canonicalized design document is kept in .figma-sync/baselines/ so diff can show what changed, not only that something changed.

  3. Design hash — the Figma node is reduced to an allowlist of design properties (name, type, geometry, fills, typography, …; ids and timestamps are dropped, and hidden subtrees are excluded), serialized as canonical JSON with sorted keys, and hashed (SHA-256).

  4. Code hash — SHA-256 over the source with normalized line endings. Regions between // figma-sync-ignore-start and // figma-sync-ignore-end are excluded, so handwritten logic there never counts as drift.

  5. Status — compares current design + code hashes against the manifest: SYNC, DESIGN_CHANGED, CODE_CHANGED, BOTH_CHANGED, NODE_DELETED, FILE_DELETED, UNMAPPED, UNKNOWN. Exit code is non-zero on any drift, so figma-sync status works as a CI gate. Output is colour-coded (no emoji) and colours auto-disable when piped or NO_COLOR is set.

Backends

Access to Figma is pluggable (lib/backends.js):

  • rest (default) — live Figma REST API; needs a FIGMA_TOKEN env var, so status reflects the current design rather than a stale snapshot. figma-sync capture refreshes all snapshots from it. When FIGMA_TOKEN is not set, commands print a warning and fall back to the snapshot backend so they still run offline (explicit --backend=rest and capture still hard-require the token).
  • snapshot — reads committed node JSON from .figma-sync/snapshots/<fileKey>/<nodeId>.json. Works offline and in CI.

Usage

figma-sync scan                # list annotated components → nodes
figma-sync update-manifest     # record current state as the baseline
figma-sync status              # drift report (non-zero exit on drift)
figma-sync diff StatusCard     # what changed in the design since baseline
figma-sync capture             # refresh snapshots from the REST API
figma-sync doctor              # validate manifest/annotations/snapshots

Typically wired into the consuming project's package.json:

{ "scripts": { "figma:status": "figma-sync status" } }

Library API (what the CLI wraps):

import { loadProject } from "@artcom/figma-sync"

const project = await loadProject()
const status = await project.status()
const diff = await project.diff("StatusCard")

Configuration

.figma-sync/config.json in the consuming project:

{ "backend": "rest", "srcDir": "src" }

designFields (the allowlist hashed for the design) can also be overridden there; see lib/config.js for the default list.

FIGMA_TOKEN (for the rest backend) is read from the environment. The CLI also auto-loads a .env file from the working directory (built-in, Node ≥ 20.12), so the token can live in the consuming project's gitignored .env. A real shell env var still takes precedence.

See docs/token-setup.md for how to create the token and exactly which scopes it needs (short answer: only file_content:read).

Limitations / next steps

  • JavaScript, not TypeScript; comment scanning uses a regex, not an AST.
  • Design freshness is pull-based; nothing watches Figma. A figmaVersion field plus the Figma versions/webhooks API would make DESIGN_CHANGED detection live instead of capture-time.
  • No tests yet; the module boundaries (mapping / backends / hash / status / reporters) are where plugin interfaces would go.