FigEx is a utility tool to export styles and icons from Figma using the Figma REST API.
Features:
- Support for modes and variables in Figma
- Code generation using Jinja2 templating syntax for any code language
- Export of icons as SVG, PDF, PNG, WEBP or Android XML vectors
- Simple configuration with many options
config.json
is a simple configuration, telling FigEx what to put where:
{
"type": "values",
"templatePath": "../samples/AndroidValues.xml.figex",
"destinationPath": "~/Downloads/AndroidValuesModeB.xml",
"defaultMode": "modeB",
"templateVariables": {
"templateVarDemo": "\uD83D\uDE80\uD83D\uDE80\uD83D\uDE80"
}
},
{
"type": "icons",
"format": "androidxml",
"filter": "{% if fullName|startsWith('icon-', true) %} true {% else %} false {% endif %}",
"fileNames" : "{{ fullName|replaceSpecialChars('_')|lowercase }}",
"destinationPath": "~/Downloads/icons",
"clearDestination": true
}
You can defined template files with Jinja-tokens to generate source code files in any language:
<?xml version="1.0" encoding="utf-8"?>
<resources>
{{ }}
{%- for color in colors -%}
<color name="{{ color.name.snake }}">#{{ color.argb }}</color>
{% endfor %}
</resources>
See the files in the samples
for a few examples! You can download the samples
folder to get
started. Go to the Figma Variables playground example and select "Open in Figma".
The file will open in your workspace and the URL will look like this:
https://www.figma.com/design/{{figmaFileKey}}/Variables-playground-(Community)?node-id=41-11&t=SPTJno70ETNtkk5D-0
Copy the {{figmaFileKey}}
section and replace the file key in samples/config.json
. Now select your profile picture in the top
left of Figma and select "Settings", then scroll down to "Personal access tokens" and create a new one. Now run figex.
This will create a samples_output
folder next to the samples
folder. Enjoy!
FigEx can be used as part of your gradle build system. Add the plugin to the root build.gradle.kts` file:
plugins {
id("com.iodigital.figex") version "{latest-version}"
}
figex {
figmaToken = "{Figma Token}"
configFile = file("path/to/config.json")
}
Now you can run ./gradlew exportFigma
to export all your Figma resources!
FigEx can be run standalone from the shell.
- Make sure Java is installed on your machine, run
java --version
to confirm - Download a
figex.zip
from the release list - Extract the zip file and place it in your system
- Create a config file for your project, see the
sample/config.json
- Create a Figma personal access token
export FIGMA_TOKEN="Figma token"
figex -c "path to your config"
set FIGMA_TOKEN="your token"
java -jar "path to figex jar" -c "path to your config"
You can make use of the FigEx core library in any Java/Kotlin project by including it in your build.gradle
file:
repositories {
mavenCentral()
}
implementation("com.iodigital:figex-core:{latest-version}")
In your code you can now use FigEx:
FigEx.exportBlocking(
configFile = "path/to/config.json",
figmaToken = "{Figma Token}",
)
Nothing to do here really! All you need is the file key from the URL. You can then use this in the configuration (see below).
We use FigEx to export a "style library" file which is not containing the actual visual designs but only colors, text styles, icons and dimensions. The design files then reference this style library. This is a small sample file: https://www.figma.com/design/0VIabis5OosbFC3Q1tYXnT
Modes in Figma allow you to have multiple values for the same variable. This can be used for light and dark modes, different brand styles or languages.
FigEx does see the modes you configured in Figma, but not the names you gave these modes. Initially, the modes will show up as their id, e.g. 834:0
.
In the logs, FigEx will list modes that you did not give a name to yet and also some sample values. Using the values, you can identify the modes and then
add a modeAliases
entry in the config.json
file. Afterwards, FigEx will represent the modes by their alias instead of their id.
See the example config in the samples
directory.
figmaFileKey
: The key for the figma file. You can obtain it from any Figma URL, the section in>>
and<<
is the key:figma.com/file/>>dqsg8P1c2ayjNJPyPYmv4X<<
modeAliases
: Aliases for the modes. FigEx sees modes only as their IDs, e.g.8124:0
and8124:1
. You can defined aliases here for your convenience. There is no way to look up the name for a mode from the free Figma API, so you need to figure out what is what.exports
: Defines the exports to be done. There are two kinds of exports:"type": "values"
is used to export any values like colors, dimensions or text stylestemplatePath
: The path to the Jinja2 template. Seesamples/AndroidValues.xml.figex
for an example and see below for more detailsdestinationPath
: The path to where the generated file should be writtendefaultMode
: The default mode to be used for the values. If thedefaultMode
is e.g.test
thencolor.test.argb
is the same ascolor.argb
templateVariables
: A map of extra variables for the template. If you definetest
here you can later use{{ test }}
in your template filefilter
: A template that should readtrue
to include a value in the export
"type": "icons"
is used to export icons and illustrationsformat
: One ofsvg
,pdf
,png
,webp
orandroidxml
filter
: A template that should readtrue
to include a component in the exportfileNames
: A template defining the file name of the exported component. A/
will cause a directory to be createddestinationPath
: The directory to which the files should be writtenclearDestination
: Iftrue
, all files in the destination directory will be deleted before exporting the iconsrasterScales
: A list of scale objects defining the sizes for raster graphics exports (png
andwebp
)scale
: A float defining the scale,1
being original sizenameSuffix
: A string that is appended to the name generated fromfileNames
, comes before the file suffixnamePrefix
: A string tha tis prepended to the name generated fromfileNames
. A/
will cause a directory to be created.
useAndroidRasterScales
: A shorthand to createmdpi
,hdpi
,xhdpi
,xxhdpi
,xxxhdpi
exports of raster graphics. Ignored ifrasterScales
is defined
The templating engine uses Jinja syntax. You can use loops, if statements and more. FigEx's templating is build with jinjava which is also the base of HubSpot's HubL templating system. This means the syntax for if-statements and loops also applies to FigEx, same goes for the filters available. Of course, HubSpot specific variables and functions are not available.
This templating is used in the filter
and fileNames
configurations.
figma
: AFigma
objectdate
: The current datefull_name
: The full name of the component. If part of a component set, comprised of the name of the component set and the component name. The component name otherwise.name
: The name of the componentkey
: The key of the componentid
: The id of the componentset_name
: The name of the set of which this component is a part of, empty if not part of a setset_key
: The ket of the set of which this component is a part of, empty if not part of a setset_id
: The id of the set of which this component is a part of, empty if not part of a setscale
: A scale object representing the current scale for the export
This templating is used in the file at the templatePath
configuration.
colors
: A list ofColor
objectsfloats
: A list ofFloat
objectsstrings
: A list ofString
objectsbooleans
: A list ofBoolean
objectstext_styles
: A list ofTextStyle
objectsfigma
: AFigma
objectdate
: The current date
name
: A name objecta
,r
,g
,b
: The alpha, red, green and blue value 0..1 (for the default mode)a255
,r255
,g255
,b255
: The alpha, red, green and blue value 0..255 (for the default mode)argb
: The argb hex string (for the default mode)modeA
: A nestedColor
object formodeA
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodeB
: A nestedColor
object formodeB
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodes
: A list of nestedColor
objects for each mode in which thename
field represents the name of the mode, not the color
name
: A name objectvalue
: The value (for the default mode)modeA
: A nestedFloat
object formodeA
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodeB
: A nestedFloat
object formodeB
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodes
: A list of nestedFloat
objects for each mode in which thename
field represents the name of the mode, not the float
name
: A name objectvalue
: A stringmodeA
: A nestedString
object formodeA
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodeB
: A nestedString
object formodeB
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodes
: A list of nestedString
objects for each mode in which thename
field represents the name of the mode, not the string
name
: A name objectvalue
: A boolean stringmodeA
: A nestedBoolean
object formodeA
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodeB
: A nestedBoolean
object formodeB
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodes
: A list of nestedBoolean
objects for each mode in which thename
field represents the name of the mode, not the boolean
name
: A name objectfont_family
: As defined in Figma (for the default mode)font_post_script_name
: As defined in Figma (for the default mode)font_size
: As defined in Figma (for the default mode)font_weight
: As defined in Figma (for the default mode)letter_spacing
: As defined in Figma (for the default mode)line_height_percent
: As defined in Figma (for the default mode)line_height_percent_font_size
: As defined in Figma (for the default mode)line_height_px
: As defined in Figma (for the default mode)line_height_unit
: As defined in Figma (for the default mode)text_align_horizontal
: As defined in Figma (for the default mode)text_align_vertical
: As defined in Figma (for the default mode)text_auto_resize
: As defined in Figma (for the default mode)modeA
: A nestedTextStyle
object formodeA
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodeB
: A nestedTextStyle
object formodeB
, contains the same values as above. The name depends on your modes and themodeAliases
in the configmodes
: A list of nestedTextStyle
objects for each mode in which thename
field represents the name of the mode, not the style
Hint: You can also use Jinja filters to modify the name, e.g. {{ color.name|lowercase|replace("some", "other") }}
original
: The name as defined in Figmasnake
: The name in snake casekebab
: The name in kebab casepascal
: The name in pascal case
file
: The Figma file namelast_modified
: Last modified date of the Figma fileversion
: The version of the Figma filefile_key
: The file key from configfile_url
: The URL of the file to open in the browser
scale
: The scale as floating point number as configuredname_prefix
: The prefix of the filename as configuredname_suffix
: The suffix of the filename as configured
- Clone the Git
- To test, open in Android Studio and
- Create a
.figmatoken
file containing your token infigex-cli/.figmatoken
- Run the
Run sample
configuration
- Create a
./gradlew clean build
will build the project and create files infigma-exported/build/distributions