Road to v2

We're big fans of Figma since pretty much the beginning so when the API was announced we immediately jumped on board and created this GraphQL API. That was the first version of the figma-graphql library and it was mostly a 1-to-1 mapping of the existing API.

As we kept using figma-graphql to get the information from our design files it became evident that the structure of the Figma API response object was very limiting.

The tree-shaped structure that the REST API uses mimics the same structure of the design file, which makes sense on one hand but on the other hand makes it quite hard for humans to process all that information.

Besides that, we were completely dismissing the power that GraphQL offers on abstracting multiple requests into a simple query.

We knew it could be much easier for people to navigate through their design files so we completely rebuilt the library for v2.

Shortcuts

We opted to surface all the different types of elements that are descendants of a given node so it makes the queries much more natural and doesn't force people to know the structure of the design file.

Let's see a concrete example. This was how we could get the name of a text element in a document:

{
file(id: "cLp23bR627jcuNSoBGkhL04E") {
pages {
frames {
elements(type: "TEXT") {
name
}
}
}
}
}

We had to follow the structure of the file and know exactly where the element was to get the information we need. This also meant that only the text elements that were direct children of the frames that were at the top level of the page would be returned.

If the designers grouped the text elements together inside those same frames, we wouldn't be able to return those elements because they'd be a child of a different element now.

In v2 this is what we can do instead:

{
file(id: "cLp23bR627jcuNSoBGkhL04E") {
pages {
frames {
texts {
name
}
}
}
}
}

Doesn't seem much of a difference but it fixes most of the issues we had with the previous query. It will return any text element that is a child of any frame that is part of any page in the file.

In this query texts, frames and pages are shortcuts and don't behave the same way as in v1. These shortcuts respect the query structure so they will only match the nodes that respect the same hierarchy in the document.

This also means that we could even simplify this query if we just want the name of all the text elements in a file, no matter where they are placed:

{
file(id: "cLp23bR627jcuNSoBGkhL04E") {
texts {
name
}
}
}

This gives a lot of flexibility and takes away the complexity of the structure of the file from the user by default.

And that was the main motivation to build the v2 of figma-graphql: to make a human-first API for Figma.

Unified query

Another aspect that we briefly mentioned above is the fact that we weren't taking advantage of the power of abstraction in GraphQL. We had the file query but also mapped all the different API end points to separate queries like images, comments, etc.

This is still possible and we kept the support from v1, but it's no longer recommended.

Instead, we are now stitching together the different queries into a single query that can do all the actions supported by the multiple queries in v1 with the added bonus that it makes the queries much easier to understand.

Let's look at this query for example:

{
projects(teamId: "teamID") {
name
files {
name
frames {
export
}
comments {
message
}
}
}
}

This is using just the team ID as a starting point to get through all the different projects inside a team, then get all the files for each project and then export all frames from each file in the default jpg format as well as getting all the comments associated with each file.

It might seem a simple query but it's in fact using four different endpoints and making several requests to get all that information. But it does that in a way that is completely hidden to the user, who doesn't have to deal witht the complexity of the system.

By making these properties available in their context we make the query much more natural and augment the capababilities of the existing REST API.