Awesome
Artsy's GraphQL Workshop
Who is this aimed at: Engineering Collaborators like design, marketing, product and anyone who is interested in how the pieces come together with our API.
Overview:
- What is an API?
- Why do we need an API?
- How come there are different types of API choices?
- What are some of our choices?
Metaphysics:
- What is metaphysics?
- Why did we build it?
- Why is it so central to writing apps at Artsy?
GraphQL
- What problem was it created to solve?
- What problems does it solve for Artsy?
How GraphQL works
We're going to use GraphQL to get info on popular Artists at Artsy.
-
Open up Metaphysics Production
-
Add the following code:
{ highlights { popularArtists(size: 1) { name } } }
-
Go through the syntax
-
Command click on
popular_artists
-
Run the query
GraphQL syntax
JSON-like. What is JSON?
{
"data": {
"highlights": {
"popularArtists": [
{
"name": "Pablo Picasso"
},
{
"name": "Banksy"
},
]
}
}
}
JSON is used to communicate between nearly all of our different services, it's considered a human-readable data format. The JS in JSON is JavaScript, and that's pretty popular.
GraphQL's syntax aims to emulate the shape of the JSON data that you're going to receive.
Scopes
{
and }
represent a scope like in JavaScript: you may have seen something like this before:
if (name == "Banksy") {
doSomethingJustForBanksy()
}
Where the code inside the braces ({
}
) will only run when that if
statement is true. In the case of GraphQL,
this is what happens when you want to get more information from something.
{
# global scope
popularArtists {
# inside here we can access properties on the PopularArtists type
}
}
It roughly looks like:
{
fieldObj {
field1
field2
}
}
We call the text inside the braces a "field", so in our current case, there is a field popular_artists
. That has
fields artists
, and that has fields like name
.
So we start at global scope, which has things like artist
, artwork
, popular_artists
and order
then we start
narrowing down the data we want.
So, with this query:
{
# global scope
highlights {
# PopularArtists
popularArtists {
# A list of Artists
# Artist scope
artists {
name
# A list of Artworks
# Artwork scope
artworks {
title
}
}
}
}
}
You can see how we can keep diving deeper through the data (we can basically do this forever, asking for an artists' artworks, which asks for the artist's for those artworks and so on)
Optional Params
Like the if statement in JavaScript, GraphQL uses (
and )
to contain arguments. Let's change out
popularArtists
query to include params:
{
highlights {
popularArtists(size: 1) {
name
}
}
}
Params are a list of color separated [name]:[value]
couplets. These are built to emulate how parameters work in
JavaScript (but with names.)
These can be simple, but sometimes aren't because we use some advanced GraphQL features. Here are some small queries that have different styles of params.
Using an array of constants for the artworksConnection
name, having some boolean values, and including params on a
resolver that doesn't have children:
{
artworksConnection(first: 5, aggregations: [TOTAL, PRICE_RANGE], acquireable: true, atAuction: false) {
edges {
node {
title
image {
url(version: "original")
}
price
artistNames
}
}
}
}
This might be enough!
This is how we build a page on the app/website - this is the query used by the Artwork page on the iPhone app:
{
artwork(id: "christo-the-gates-project-for-central-park-5") {
slug
internalID
artist {
slug
internalID
name
years
birthday
nationality
blurb
image {
url
}
sortableID
}
partner {
name
slug
defaultProfileID
isDefaultProfilePublic
type
href
}
images {
imageVersions
imageURL
isDefault
originalHeight
originalWidth
aspectRatio
maxTiledHeight
maxTiledWidth
tileSize
tileBaseURL
tileFormat
}
dimensions {
cm
in
}
attributionClass {
name
}
editionSets {
saleMessage
isSold
isForSale
dimensions {
in
cm
}
}
availability
additionalInformation
category
collectingInstitution
date
exhibitionHistory
editionOf
imageRights
isForSale
isPriceHidden
isSold
isInquireable
shippingInfo
shippingOrigin
literature
medium
price
provenance
published
saleMessage
series
signature
title
}
}
It's a lot of data, but it's a complex page. We do other work on the page, but this gets the main artwork metadata.
Docs
So, we know enough to be dangerous. Now what? I think it's worth digging into the how we can figure out what how to find things we're interested in.
Using the sidebar
The sidebar on the left represents the types of objects that exist inside our API. In simple, everything is a type.
There are two "root" types Query
and Mutation
. A mutation, roughly, represents a change to the database, like
following an Artist.
We're interested in the other: Query
. If you click on the word Query
in the right sidebar, it will show you all
of the available fields. These are the things that you can start your query with from the global scope.
This gives you the ability to jump through the connections between things without writing code, and you can see our docs about what things are and how they come together.
Guess by typing
Generally, I work this way.
Logging in
We're currently working with all public data. Sometimes, you'll need to log in with your user account. This is a bit tricky. To do this you're going to need to set up some request headers. This is a bit of a thing, sorry. I might be able to improve this in the future, but for now you'll need to download an app.
- Go here: https://electronjs.org/apps/graphiql
- Click on
GraphiQL-0.7.x.dmg
in the sidebar - Click on the new DMG in your downloads
- Drag the app into Applications
- Open it from your Applications folder
That opens up the GraphQL app. First, let's just to Chrome. Open the artsy website artsy.net and we need to go into the developer tools.
-
Press
alt + cmd + i
, this should open up a window that represents the developer tools for Chrome -
In the bottom half of the window, there is a section called "Console". You want to run this code in there:
sd.CURRENT_USER.accessToken
-
This will output something like:
"eyJ0eXAiOiJKV4QiLCiJIUzI1NiJ9.asdaffvcsdkjsbksg .bY8n_s0dK6P6VHASDA3gtcV7QVi_iTx2GXr58mCzk"
- Select the text and copy it.
Now we have your access token, let's add it to the GraphiQL app.
- Click on "Edit HTTP Headers"
- Click on "Add Header"
- Paste your token in the "Header Value"
- Set the "Header name" to be "x-access-token"
- Hit save
- Click outside of the white box to get rid of the modal
- Set the GraphQL Endpoint to be: https://metaphysics-production.artsy.net/v2
OK! Now you are logged in.
Let's verify this by running this query:
{
me {
name
email
}
}
If you get a response like:
{
"data": {
"me": null
}
}
Then the header for your access token is not hooked up correctly.
Now you're connected
Let's take a look at your followed Artists:
{
me {
followArtists {
artists {
name
}
}
}
}
Nearly all of the information related to a user account is structured inside the me {
.
What now?
Ideally, I'd like some ideas on bits of data we can look up, and I'll try show how to find it.
Other than that, I've left a bunch of example queries in the examples/
folder in this repo.