├── .gitignore ├── README.md ├── app.json ├── images ├── add-to-version-history.png ├── copy-personal-access-token.png ├── created-webhook-url.png ├── figma-dropdown.png ├── logo.png ├── publish-library.png ├── scheduler-new-job.png ├── updates.jpg └── version-history.png ├── requirements.txt └── update.py /.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](images/logo.png) 2 | # Figma Slack updates 3 | Automatically post updates to a Slack channel each day with the updates from a Figma file's version history. [View example](https://twitter.com/jsngr/status/1208161921687576577) 4 | 5 | - [Setting up](#setting-up) 6 | - [Heroku](#heroku) 7 | - [Deploying the Heroku app](#deploying-the-heroku-app) 8 | - [Setting up your Heroku app](#setting-up-your-heroku-app) 9 | - [Customizing your job](#customizing-your-job) 10 | - [Testing that it worked](#testing-that-it-worked) 11 | - [Figma](#figma) 12 | - [Get a Personal Access Token](#get-a-personal-access-token) 13 | - [Get your file key](#get-your-file-key) 14 | - [Slack](#slack) 15 | - [Create a new Slack app](#create-a-new-slack-app) 16 | - [Activate Incoming Webhooks](#activate-incoming-webhooks) 17 | - [Figma Version History](#figma-version-history) 18 | - [Publishing changes](#publishing-changes) 19 | - [Slack updates](#slack-updates) 20 | 21 | ## Setting up 22 | 23 | ### Heroku 24 | #### Deploying the Heroku app 25 | 1. Click the Deploy to Heroku button 26 | 27 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/jordansinger/figma-slack-updates) 28 | 29 | 2. Give your Heroku app a name 30 | 3. For the **Config Vars** section, proceed to the [Figma](#figma) and [Slack](#slack) sections of the README in order to obtain your `FIGMA_FILE_KEY`, `FIGMA_PERSONAL_ACCESS_TOKEN`, `SLACK_CHANNEL_ID`, `SLACK_TEAM_ID`, `SLACK_USER_ID` 31 | 3. Click "Deploy app" 32 | 33 | #### Setting up your Heroku app 34 | 1. After the deploy is successful, click on "Manage App" 35 | 2. Click on "Heroku Scheduler" in the **Installed add-ons** section 36 | 3. Click on "Create job" 37 | 4. [Customize your job](#customizing-your-job) 38 | 39 | #### Customizing your job 40 | 1. In the **Schedule** section, set the interval to "Every day at..." and choose a time (in UTC) that works best for you 41 | 2. In the **Run Command** section, set the command to `python update.py` 42 | 3. Click on "Save Job" 43 | 44 | #### Testing that it worked 45 | First, in the Figma file that you grabbed the file key for earlier, [make some changes and create a version](#figma-version-history). 46 | 47 | 1. In the dashboard for the app that you created in Heroku, click on "More" in the top right corner, and then "Run console" 48 | 2. Enter `python update.py` and click "Run" 49 | 3. Your changes should be posted to Slack 🎉 50 | 51 | Now that you're all set up, your Slack channel will receive updates every day at the time you've selected your Heroku Scheduler job to run (assuming changes were made in Figma). 52 | 53 | If there was an issue while running, first make sure to double check that your Config Vars are correct in the Settings section of your Heroku app. If you're still running into an issue, be sure to [create an issue](https://github.com/jordansinger/figma-slack-updates/issues). 54 | 55 | ### Figma 56 | #### Get a Personal Access Token 57 | 1. While logged into Figma on the web or the desktop app, visit your [Account Settings](https://www.figma.com/settings) 58 | 2. Under **Personal Access Tokens**, click "Create a new personal access token" 59 | 3. Name the the access token whatever you'd like, for example: `figma-slack-updates` 60 | 3. Copy the token - this is your only chance to do so! This is your `FIGMA_PERSONAL_ACCESS_TOKEN` 61 | ![Copy Personal Access Tokens](images/copy-personal-access-token.png) 62 | 63 | #### Get your file key 64 | Visit the Figma file that you'd like to post updates for and copy its `file key`. The file key can be found when you copy the file's link or visit the file on the web: figma.com/file/`file key`/... This is your `FIGMA_FILE_KEY` 65 | 66 | ### Slack 67 | #### Create a new Slack app 68 | 1. While logged into Slack on the web, visit [Your Apps](https://api.slack.com/apps) 69 | 2. Click on "Create New App". Give it a name and a team to post in. 70 | 71 | #### Activate Incoming Webhooks 72 | 1. After the app is created, visit **Incoming Webhooks** 73 | 2. Turn the **Activate Incoming Webhooks** toggle on 74 | 3. Under **Webhook URLs for Your Workspace**, click "Add New Webhook to Workspace" 75 | 4. Choose a channel for the Slack app to post updates to 76 | 5. Under **Webhook URLs for Your Workspace**, take note of the code inside of "Sample curl request to post to a channel". There are three pieces of info to copy from the URL: the team ID, user ID, and channel ID. hooks.slack.com/services/`team id`/`user id`/`channel id`. In sequential order, these are your `SLACK_TEAM_ID`, `SLACK_USER_ID`, and `SLACK_CHANNEL_ID` 77 | ![Webhook URLs for Your Workspace](images/created-webhook-url.png) 78 | 79 | ## Figma Version History 80 | 81 | ### Publishing changes 82 | In the Figma file that you set up to post changes from, you can either publish your component changes or create a new version in your file's version history. Both of these kinds of changes will be posted to Slack. 83 | ###### Note: The "Description" field for each of these is required in order for it to be posted to Slack. If there is no description provided, the changes won't be mentioned in Slack. 84 | ![Figma Version History](images/add-to-version-history.png) 85 | 86 | ### Slack updates 87 | Slack posts will happen every day at the time you've selected your Heroku Scheduler job to run (assuming changes were made in Figma). They'll appear with the date of the changes, followed by a list of all of your changes for that given day. 88 | ###### It's recommended that your descriptions for changes are prefixed with a "-" and followed by a newline. 89 | ![Slack posts](images/updates.jpg) 90 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Figma Slack updates", 3 | "description": "Post updates to Slack from a Figma file's version history", 4 | "repository": "https://github.com/jordansinger/figma-slack-updates", 5 | "logo": "https://github.com/jordansinger/figma-slack-updates/blob/master/images/logo.png?raw=true", 6 | "env": { 7 | "FIGMA_PERSONAL_ACCESS_TOKEN": { 8 | "description": "The Figma Personal Access Token created for your account" 9 | }, 10 | "FIGMA_FILE_KEY": { 11 | "description": "The Figma file key to post updates from" 12 | }, 13 | "SLACK_TEAM_ID": { 14 | "description": "The team ID from the Slack Webhook URL" 15 | }, 16 | "SLACK_USER_ID": { 17 | "description": "The user ID from the Slack Webhook URL" 18 | }, 19 | "SLACK_CHANNEL_ID": { 20 | "description": "The channel ID from the Slack Webhook URL" 21 | } 22 | }, 23 | "addons": [ 24 | "scheduler" 25 | ] 26 | } -------------------------------------------------------------------------------- /images/add-to-version-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/add-to-version-history.png -------------------------------------------------------------------------------- /images/copy-personal-access-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/copy-personal-access-token.png -------------------------------------------------------------------------------- /images/created-webhook-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/created-webhook-url.png -------------------------------------------------------------------------------- /images/figma-dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/figma-dropdown.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/logo.png -------------------------------------------------------------------------------- /images/publish-library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/publish-library.png -------------------------------------------------------------------------------- /images/scheduler-new-job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/scheduler-new-job.png -------------------------------------------------------------------------------- /images/updates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/updates.jpg -------------------------------------------------------------------------------- /images/version-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jordansinger/figma-slack-updates/4cf5b537418a461506501bd27f501448b74b5e6d/images/version-history.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | maya==0.6.1 2 | requests==2.18.4 3 | python-dotenv==0.12.0 -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import maya 3 | import datetime 4 | from os import environ 5 | from dotenv import load_dotenv 6 | load_dotenv() 7 | 8 | def get_updates(): 9 | FIGMA_PERSONAL_ACCESS_TOKEN = environ.get('FIGMA_PERSONAL_ACCESS_TOKEN') 10 | FIGMA_FILE_KEY = environ.get('FIGMA_FILE_KEY') 11 | FIGMA_API_URL = "https://api.figma.com/v1/files/" + FIGMA_FILE_KEY + "/versions" 12 | FIGMA_API_HEADERS = { 'X-FIGMA-TOKEN': FIGMA_PERSONAL_ACCESS_TOKEN } 13 | 14 | r = requests.get(url = FIGMA_API_URL, headers = FIGMA_API_HEADERS) 15 | data = r.json() 16 | versions = data["versions"] 17 | 18 | filter_function = lambda x: maya.parse(x['created_at']).datetime().date() == datetime.date.today() and x['description'] is not None and len(x['description']) > 0 19 | todays_versions = list(filter(filter_function, versions)) 20 | if len(todays_versions) > 0: 21 | message = format_message(todays_versions) 22 | post_message(message) 23 | 24 | def format_message(todays_versions): 25 | date = datetime.datetime.today() 26 | message = str(date.month) + "/" + str(date.day) + "\n" 27 | 28 | for version in todays_versions: 29 | description = version["description"] 30 | message += "\n" + description 31 | 32 | return message 33 | 34 | def post_message(message): 35 | SLACK_TEAM_ID = environ.get('SLACK_TEAM_ID') 36 | SLACK_USER_ID = environ.get('SLACK_USER_ID') 37 | SLACK_CHANNEL_ID = environ.get('SLACK_CHANNEL_ID') 38 | SLACK_API_URL = "https://hooks.slack.com/services/" + SLACK_TEAM_ID + "/" + SLACK_USER_ID + "/" + SLACK_CHANNEL_ID 39 | 40 | data = { "text": message } 41 | r = requests.post(url = SLACK_API_URL, json = data) 42 | print(message) 43 | 44 | get_updates() 45 | --------------------------------------------------------------------------------