Skip to content

figma-export-assets (JS module)

A few months ago I started developing a CLI to easily start a design system with Figma as the single source of truth for logos and icons. These assets were organized as components on a Figma page, and my goal for easy updates was to pull them programmaticaly into my project using Figma's API. My specific needs were:

  1. Download all logos as .svg and .png into src/logos.
  2. Download all icons (>2000!) into src/icons
Screenshot of Figma. There are two areas, one for assets/logos, which export to .svg + .png and one for assets/icons, which export .svg.
Screenshot of logos and icons in Figma

I aimed for this output:

src

├── logos
   ├── logo-stylized.svg
   ├── logo-stylized.png
   ├── logo-wordmark.png
   └── logo-wordmark.svg

└── icons
    ├── activity.svg
    ├── alarm.svg
    ├── alarm-fill.svg
    ├── ...
    ├── // other >2000 icons
    ├── ...
    └── zoom-out.svg

I quickly found some Node packages, but there were bugs or missing features:

  1. There wasn't an option to set multiple formats for specific assets.
  2. It was impossible to ignore certain layers.
  3. >400 requested exports exceeded Figma's Export API, but batching was not implemented.
  4. There was no feature to customize file paths per asset.

I decided to take it into my own hands, forked figma-export-icons, took some inspiration from figma-assets-exporter and rewrote it to make it super customizable.

figma-export-assets

The result figma-export-assets is of course available on GitHub and NPM – and I'm actually quite happy with the functionality of the package (shamelessly copied from the docs):

  • 📄 Multiple Figma Pages/Frames: Configure to process assets from various Figma pages or specific frames.
  • 🔄 Batch Exporting: Supports batch exporting out of the box to overcame Figma API export limits.
  • 📁 Customizable Asset Paths/Names: Set unique saving paths or names for each asset.
  • 🌈 Customizable Asset Format: Chose any Figma export format for each asset.
  • 🚫 Asset Exclusion: Easily exclude specific assets from export based on their names.
  • ⚙️ Axios Integration: Extend or modify Axios configurations for advanced HTTP request handling.
  • 🌟 Variant Exporting: Overridable option to export components with variants as separate assets.

Here’s how it works for my initial requirements:

require("dotenv").config({ path: ".env" });
const { FigmaExporter } = require("figma-export-assets");

// Helper function to optimize path coming from Figma
const optimizePath = (path) =>
		path.replace("assets/", "").replace("name=", "").replace(".png", "");

async function main() {
	// 0. Initialize exporter
	const figma = new FigmaExporter({
	    figmaPersonalToken: process.env.figma_token,
	    fileId: process.env.figma_file_id,
	    page: "📎 assets",
	    assetsPath: "src",
    });

	// 1. Get an array of all assets in the Figma file
	let assets = await figma.getAssets();

	// 2. Create PNGs from logos
	let pngs = assets.filter((asset) => asset.name.includes("assets/logos"));
	pngs = await figma.exportAssets(pngs, "png", 4);
	const pngDownloads = pngs.map(async (asset) => {
		await figma.saveAsset(asset, {
			path: optimizePath(asset.name),
		});
		console.log(`Downloaded ${asset.name} as png`);
	});
	await Promise.all(pngDownloads);

	// 3. Create SVGs from logos and icons
	svgs = await figma.exportAssets(assets, "svg");
	const svgDownloads = svgs.map(async (asset) => {
		await figma.saveAsset(asset, {
			name: optimizePath(asset.name),
		});
		console.log(`Downloaded ${asset.name} as svg`);
	});
	await Promise.all(svgDownloads);
}

// Run everything
main();

Broader usage

Of course this isn't limited to just icons or logos –  It can be used with any imagery like photos, Open Graph images, illustrations etc., making it a nice tool to automize workflows between Figma and development.

For my personal project it was just perfect, and to my delight, just a few weeks later it was implemented in one Design System I'm part of. 🎉

Looking forward to other usages – maybe yours? 😉

Reactions on Mastodon Post:

2
1
0