1
1 Comment

How to automate logo creation in Figma with bots

If you're doing repetitive tasks such as creating logos for clients and yourself in Figma, you can automate the whole process with bots.

Follow along to learn how to create this bot that can create and export a new logo in less than 30 seconds:

Full walkthrough

Here are the steps we're going to take:

1. Preparation

2. Log in to your Figma account

3. Create logo

4. Export and download logo zip file

Let's create a logo for a client. They are asking for a logo for their website cashewcoffee.com


1. Preparation

Here's what we'll use:

1. Python 🐍

2. Selenium WebDriver 🤖

3. Chrome web browser ⚙️

To be able to interact with websites with Selenium, we need to locate the full XPath of each element we want to interact with.
If you like to type your email in the text field where you're writing your email, you need to locate the XPath for that particular text field.

The first step is installing and then importing all the Selenium packages. You'll find installation guides here https://pypi.org/project/selenium/

Once you have Selenium and a Chrome driver, go ahead and import the packages:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC

Before we start the browser and log in to our Figma account, let's create 2 functions for common operations that we'll use throughout the automation; writing in text areas and clicking on buttons.

1. Function for typing in text areas

This function will locate an element according to its full XPath, click in the text area, and type each word in a string with a 400-millisecond delay.

def type_in_text_area(element_xpath, text_string, delay=2):
    """
    Type words into a text area
    """

    # Find text area with its XPath
    text_area = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, element_xpath)))

    # Start an action chain
    action = ActionChains(driver)
    action.move_to_element(text_area).click().perform()
    sleep(0.4)

    for letter in text_string:
        text_area.send_keys(letter)
        sleep(0.009)

2. Function for clicking on buttons

This function will locate an element according to its full XPath and hold-click on it.

def click_hold_button(element_xpath, delay=2):
    """
    Click and hold a button
    """

    button = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.XPATH, element_xpath)))
    webdriver.ActionChains(driver).click_and_hold(button).perform()
    sleep(0.5)
    webdriver.ActionChains(driver).release().perform()

2. Login to your Figma account

Start the web driver; this will open a new Chrome window:

driver = webdriver.Chrome()

Define the pages you like to route to when the web driver is up and visit the page:

page = "https://www.figma.com/files/drafts"
driver.get(page)

driver.get(page) will take you to the login page of Figma. To log in and start the project, create two variables with your login credentials:

email = "YOUR_FIGMA_EMAIL"
passw = "YOUR_FIGMA_PASSWORD"

You can now type your email into the email text field by locating the XPath for the text field. Locate the XPath by inspecting the text field. Start by right-clicking on the element and choosing inspect in the menu.

Inspect the element you want to interact with

If the inspector happens to open up to the right (or left) - make sure to dock it to the bottom:

Dock the inspector to the bottom

Here's how the inspector should be docked to the bottom, and you'll also see a banner saying that Chrome is being controlled by automated test software:

Inspector docked to the bottom

Inspect the text area by first clicking on (1) and then click on (2):

Select an element to inspect

Once you have clicked on the element you'd like to inspect, you'll see the element highlighted in the inspector:

Highlighted element in the inspector

To get the full XPath of the inspected element, right-click in the highlighted area, hover Copy, and finally click on Copy full XPath

Copy full XPath of inspected element

Now that you have the full XPath copied, return to the code and create a variable with the path:

email_path = "/html/body/div[1]/div/div[1]/form/input[1]"

Do the same for the XPath of the password text field:

Copy full XPath of password text area

Add the copied XPath of the password text field to the code:

passw_path = "/html/body/div[1]/div/div[1]/form/input[2]"

The last element needed to be able to log in is the XPath of the log-in button. Follow the same procedure and copy the XPath of the login button. The final code snippet with the 3 XPaths should look something like this:

email_path = "/html/body/div[1]/div/div[1]/form/input[1]"
passw_path = "/html/body/div[1]/div/div[1]/form/input[2]"
login_button = "/html/body/div[1]/div/div[1]/form/button[2]"

Next, write your email address and password to the text fields and click on the login button. For this, we'll use the two functions we created earlier.

Run this snippet, and you should see the text fields get populated with your email and password, and then the log-in button gets clicked.

email = "YOUR_FIGMA_EMAIL"
passw = "YOUR_FIGMA_PASSWORD"

email_path = "/html/body/div[1]/div/div[1]/form/input[1]"
passw_path = "/html/body/div[1]/div/div[1]/form/input[2]"
login_button = "/html/body/div[1]/div/div[1]/form/button[2]"

type_in_text_area(email_path, email)
type_in_text_area(passw_path, passw)
sleep(1)

click_hold_button(login_button)

Run the code and you should now see your Figma dashboard:

Figma dashboard

Let's head over to the next part, creating a new design file and a logo.


3. Create the logo

The first step of creating a logo now that we're logged in is to create a new design file. The full XPath to create a new file is /html/body/div[2]/div/div/div[1]/div[3]/div[5]/div[3]/a[1] combine that with clicking on the button like this:

# Create new design file
new_design_file_xpath = "/html/body/div[2]/div/div/div[1]/div[3]/div[5]/div[3]/a[1]"

click_hold_button(new_design_file_xpath)
sleep(1)

Now that we have a new design file, let's use the Figma shortcut T to switch to the text tool and create a new text.

# Pick the text tool
text_tool_xpath = "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[2]/div[5]"

click_hold_button(text_tool_xpath)
sleep(1)

When the text tool is chosen, go ahead and click on the canvas and start typing the logo text:

# Click on canvas
canvas_xpath = "/html/body/div[2]/div/div/div[1]/div/div[1]/div/div/div/div[1]/div/div/canvas"
click_hold_button(canvas_xpath)
sleep(1)

# Write logo text
logo_text = "LOGO_TEXT"
ActionChains(driver).send_keys(logo_text).perform()
sleep(1)

Time to change the font size and pick the font you want to use for the logo. I'll go with 100 pt and the font Mama and Papa.

Highlight the logo text first. This snippet runs the command ⌘ + a - if you're in Windows, switch Keys.COMMAND to Keys.CONTROL instead.

# Highlight logo text
# Use Keys.CONTROL if on Windows, Keys.COMMAND is for MacOS
ActionChains(driver).key_down(Keys.COMMAND).send_keys('a').key_up(Keys.COMMAND).perform()

Click on the font size and delete the current size:

# Click on font size
font_size_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[5]/div/div[1]/div[3]/div[2]/div[2]/div/label/input"
font_size_area = driver.find_element(By.XPATH, font_size_xpath)
sleep(1)

# Delete font size
font_size_area.send_keys(Keys.DELETE)

Choose a new font size and finish by pressing the return key:

# Choose a new font size
size = "100"
type_in_text_area(font_size_element, size)
sleep(1)

# Confirm new font size
ActionChains(driver).send_keys(Keys.ENTER).perform()

Font size is updated, now change to the font you want to use for the logo:

# Click on font
font_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div[1]/div/div[1]/span/span[2]/div[5]/div/div[1]/div[3]/div[1]/div/input"

click_hold_button(font_xpath)
font_textfield = driver.find_element(By.XPATH, font_name_input)
sleep(1)

# Delete the current font
font_textfield.send_keys(Keys.BACK_SPACE)
sleep(1)

font_name = "YOUR_FONT"

# Type new font name
font_name_area.send_keys(font_name)
font_name_area.send_keys(Keys.ENTER)
sleep(1)

So far, we have written the logo text and changed the size and font. The last step is to vectorize the text and duplicate the layer into 3 colors.

Start with hitting the escape key to deselect the logo layer:

ActionChains(driver).key_down(Keys.ESCAPE).key_up(Keys.ESCAPE).perform()
sleep(1)

Then vectorize the text layer and duplicate the flattened layer:

# Vectroize text layer by flatten the text
ActionChains(driver).key_down(Keys.COMMAND).send_keys("e").perform()
sleep(1)

# Duplicate once
ActionChains(driver).key_down(Keys.COMMAND).send_keys("d").perform()
sleep(1)

# Duplicate again
ActionChains(driver).key_down(Keys.COMMAND).send_keys("d").perform()
sleep(1)

Used shortcuts:

⌘ + e = flatten text layer to vectorize

⌘ + d = duplicate layer

⌘ + r = rename layer

⌘ + a = select all layers

If you're on Windows, switch all Keys.COMMAND to Keys.CONTROL


We duplicated the layer to create 3 different versions of the logo, one in white, black, and color of your choice. Let's rename the layers to keep track of each one:

# First layer is already selected
# Change name to white
# Use Keys.CONTROL if on Windows, Keys.COMMAND is for MacOS
ActionChains(driver).key_down(Keys.COMMAND).send_keys("r").key_up(Keys.COMMAND).send_keys(Keys.ARROW_RIGHT).send_keys(' white').send_keys(Keys.ENTER).perform()
sleep(1)

# Change vector color to white
color_picker_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[8]/div/div/div[3]/div/div/div/div/div/div/div[1]/div/div/div"
click_hold_button(color_picker_xpath)
ActionChains(driver).send_keys("ffffff").perform()
click_hold_button(color_picker_xpath)

# Click on second layer
vector_layer_2 = "/html/body/div[2]/div/div/div[1]/div/div[9]/div[1]/div/div[2]/div/div/div/div/div[1]/div[2]/span[3]"
click_hold_button(vector_layer_2)
sleep(1)

# Change name to black
ActionChains(driver).key_down(Keys.COMMAND).send_keys("r").key_up(Keys.COMMAND).send_keys(Keys.ARROW_RIGHT).send_keys(' black').send_keys(Keys.ENTER).perform()

# Change vector color to black
click_hold_button(color_picker_xpath)
ActionChains(driver).send_keys("000000").perform()
click_hold_button(color_picker_xpath)

# Click last layer
vector_layer_3 = "/html/body/div[2]/div/div/div[1]/div/div[9]/div[1]/div/div[2]/div/div/div/div/div[1]/div[1]/span[3]"
click_hold_button(vector_layer_3)
sleep(1)

# Recolor last layer
logo_color = "YOUR_LOGO_COLOR"
click_hold_button(color_picker_xpath)
ActionChains(driver).send_keys(logo_color).perform()
click_hold_button(color_picker_xpath)
sleep(1)

The logo and its different color variants are all set. The last step is exporting the logo in 3 different file formats: PNG, JPG, and SVG.


4. Export the logo and save it in 3 file formats

Start with selecting all the layers to export all of them at once:

# Select all layers
# Use Keys.CONTROL if on Windows, Keys.COMMAND is for MacOS
ActionChains(driver).key_down(Keys.COMMAND).send_keys('a').key_up(Keys.COMMAND).perform()
sleep(1)

Next up is clicking on the export panel to start exporting:

export_panel_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div"
click_hold_button(export_panel_xpath)
sleep(1)

The first format is now png. Let's create another file format by clicking on the plus sign:

plus_button_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div/div[1]/div[1]/div/div[2]/span[2]"
click_hold_button(plus_button_xpath)
sleep(1)

This will automatically add a version 2x the size and with a pre-populated suffix. I want all the files in the same magnification, so let's change back to 1x size:

size_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div/div[1]/div[2]/div[1]/div/div/div[2]/input"
click_hold_button(size_xpath)

ActionChains(driver).send_keys("1x").send_keys(Keys.ENTER).perform()
sleep(1)

Go ahead and delete the suffix as well:

# Click on the suffix
suffix_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div/div[1]/div[2]/div[1]/div/div/input"
click_hold_button(suffix_xpath)

# Delete suffix
ActionChains(driver).send_keys(Keys.BACKSPACE).send_keys(Keys.BACKSPACE).send_keys(Keys.BACKSPACE).perform()
sleep(1)

Choose JPG for the file type:

# Choose JPG as file type
dropdown_file_type_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div/div[1]/div[2]/div[1]/div/div/div[3]/div[2]/span[1]"

dropdown_button = WebDriverWait(driver, 4).until(EC.presence_of_element_located((By.XPATH, dropdown_file_type_xpath)))
dropdown_button.click()
sleep(1)

# Use arrows to navigate in the dropdown
webdriver.ActionChains(driver).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ENTER).perform()
sleep(1)

Lastly, add a new export file and choose SVG as the file type:

# Add new file type
click_hold_button(plus_button_xpath)
sleep(1)

# Change suffix for SVG
click_hold_button(suffix_xpath)
sleep(1)

# Delete the suffix
ActionChains(driver).send_keys(Keys.BACK_SPACE).send_keys(Keys.BACK_SPACE).send_keys(Keys.BACK_SPACE).send_keys(Keys.ENTER).perform()
sleep(1)

# Use arrow keys to navigate in dropdown list
dropdown_button = WebDriverWait(driver, 4).until(EC.presence_of_element_located((By.XPATH, dropdown_file_type_xpath)))
dropdown_button.click()
webdriver.ActionChains(driver).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ENTER).perform()

Finally, click on export:

export_button_xpath = "/html/body/div[2]/div/div/div[1]/div/div[10]/div/div/div[2]/div/div/div/div[1]/span/span[2]/div[13]/div/div[2]/div/button"

click_hold_button(export_button_xpath)

Here's what the complete walkthrough looks like when you run all the code:

Full walkthrough

And here's the final logo I created for the client:

Final logo


Summary

1. Preparation

2. Log in to your Figma account

3. Create logo

4. Export and download logo zip file


Next steps

1. Repo with source code

Here is the repo with a Jupyter notebook with all the source code if you'd like to implement this on your own ⬇️
https://github.com/norahsakal/automate-logo-creation-in-figma

2. Want this but don't feel like coding?

Shoot me a DM on Twitter, I'd love to help out @norahsakal

3. Looking for your next business idea or a new side project? 💡

If you liked the logo, you might enjoy my weekly newsletter; Daily Domain Ideas
Every Monday you'll get 3 business ideas with expired .com domains

The domain cashewcoffee.com is actually expired and was part of the newsletter issue #016
Idea: A site for finding recipes to make a rich, foamy, creamy cashew coffee ⬇️

Final logo


Originally published at https://norahsakal.com/blog/automate-logo-creation-in-figma

posted to Icon for group Developers
Developers
on August 19, 2022
  1. 2

    This comment was deleted 2 years ago.

    1. 2

      Thanks for your feedback, I really appreciate it!

      I'm using Selenium for all my end-to-end testing, and unless you change the elements you're testing, it's pretty stable.

      Totally agree with you regarding sleep(), especially with production code.
      Thanks again for your thoughts!

Trending on Indie Hackers
How we got 100+ clients in 48 hours from Product Hunt User Avatar 16 comments Meme marketing for startups 🔥 User Avatar 11 comments After 19,314 lines of code, i'm shutting down my project User Avatar 1 comment Need feedback for my product. User Avatar 1 comment We are live on Product Hunt User Avatar 1 comment Don't be a Jerk. Use this Tip Calculator. User Avatar 1 comment