Instrument x Seth Akkerman
Projects Figma Variant Usage Tracker

Figma Variant Usage Tracker

A Figma plugin that scans your entire file and counts how many times each component variant is actually used — then stamps that count directly next to the variant in your component set.

The question came up: how often is each variant in a component set actually being used across a file? There are a handful of plugins that touch on this, but they’re limited, don’t surface the data in a useful way, or cost money. So the obvious move was to build one.

How it works

Select a component or variant set, hit Count Usage, and the plugin traverses every page in the Figma file — loading all pages asynchronously — collecting every instance node it can find. It then resolves each instance back to its main component, checks whether that component belongs to a component set, and tallies the count per variant name. The result is a breakdown showing exactly how many times each variant appears across the document. From there, a second action — Add Count Labels — writes that number as a text element six pixels to the right of each variant inside the component set, giving you a live, at-a-glance reference without leaving the canvas.

The build

The plugin is written in TypeScript against the Figma Plugin API, compiled down to vanilla JS for the browser runtime. The UI is intentionally minimal: a three-step workflow card, a primary count action, a label-writing action, and an advanced mode for scanning all components in the file at once. State is tracked in the UI layer so the label-writing step always has fresh counts to work from without re-scanning.

Why it matters

Variant usage data is genuinely useful for design system maintenance. Knowing that one status label variant appears 92 times while another appears twice changes how confidently you deprecate, rename, or restructure components. This same pattern — scan, count, annotate — could extend to: design system audits where teams want to see which components are over- or under-used before a refactor; handoff documentation where usage counts surface automatically alongside specs; or component retirement workflows where zero-count variants get flagged for cleanup. It’s a small plugin, but the underlying approach of resolving instances back to their component sets and writing metadata directly into the canvas is a reusable pattern worth building on.

Applying this to your project

  1. Copy the whole VariantTracker folder as your starting point — code.ts (plugin logic), ui.html (plugin UI), manifest.json, tsconfig.json, and package.json. Discard node_modules, code.js, and package-lock.json — these are all regenerated by running npm install then npm run build (per the scripts in package.json), and code.js is git-ignored for a reason.
  2. No API keys or accounts to set up. manifest.json has "networkAccess": { "allowedDomains": ["none"] }, so the plugin is fully offline. If your adaptation needs to call an external service, you’ll need to add that domain to allowedDomains and handle the request from code.ts (Figma blocks network calls from anywhere else in the plugin).
  3. To make it your own: change name and id in manifest.json (the id is a Figma-issued unique identifier — you’ll get a new one automatically when you create a new plugin in the Figma desktop app, so don’t just hand-copy the old one). Update the copy inside the .workflow div and the <h3> title in ui.html to describe your own tool, and restyle the .button/.workflow CSS classes to match your brand colors instead of Figma’s default blue (#18A0FB).
  4. The critical integration point is the message-passing contract between code.ts and ui.html: figma.ui.onmessage in code.ts listens for type strings ('count-variants', 'count-selected-only', 'update-variants'), and ui.html sends them via parent.postMessage({ pluginMessage: { type: ... } }, '*'), then reads results back in window.onmessage. Any new feature means adding a matching type on both sides — if you add a button in ui.html without a corresponding case in code.ts’s onmessage handler, it’ll silently do nothing.
  5. Gotchas found in the code: (a) updateVariantsWithCounts hardcodes figma.loadFontAsync({ family: "Inter", style: "Regular" }) and "Bold" — if the target file doesn’t have Inter loaded, or you want a different font, you must change both font-load calls or it’ll throw. (b) The count-matching logic first tries an exact match on variant.name, then falls back to matching a single variant-property value — it does not handle component sets with multiple variant properties well (see the propertyKeys.length > 1 branch in code.ts), so counts can silently show as 0 for complex variant sets. (c) Count labels are found on re-run by searching for text nodes named `${variant.name}-usage-count` — renaming a variant or the generated label breaks the “update in place” behavior and creates duplicates instead. (d) documentAccess: "dynamic-page" plus figma.loadAllPagesAsync() means the “Advanced: Count All Components” button loads every page in the file before scanning — this can be slow on large files.

Other ways to repurpose this

Product Design

Web Design

Marketing

Branding

Dependencies

@figma/plugin-typings 1.116.0 Provides TypeScript type definitions for the Figma Plugin API (figma.*, InstanceNode, ComponentSetNode, etc.) so code.ts gets autocomplete and type-checking against the actual plugin sandbox globals.
typescript 5.9.2 Compiles the source in code.ts into the code.js file that manifest.json points to as the plugin's runnable entry point.
Role
Design Engineer
Tools
Figma Plugin API TypeScript JavaScript
Video thumbnail for Figma Variant Usage Tracker