There's something joyful about a sticker - the glossy laminated colors, the pure potential before you peel away the backing and decide whether to display it on a laptop, water bottle, or skateboard. Stickers, like mini badges of honor, reflect your lived experiences.

So when it came to swag, stickers were an obvious choice for us here at StepZen.

But how to get them to you? The simplest way was to use our own service!

Read on to see how we collected and verified your address information to send you our stickers-- see exactly how StepZen's GraphQL data layer brought ease to our integration of two initially separate backends.

The Overall Structure of the Code

Since our website was a Next app, we added a stickers.js page in the /pages directory to display the UI and take in the information for the GraphQL query from the user.

Next.js has a very easy way of creating pages. If you add any javascript file to the directory pages/, it will create that route in the application.

We imported a route, pages/api that executes HTTP fetch calls to a StepZen GraphQL endpoint and requires API key authentication to access.

We imported the fetch calls themselves from the Next pages/api folder.

These calls were made to a StepZen endpoint, which was setup with a StepZen folder. Let's go into a little more detail on this folder's structure.

Keep the file structure code block --- The StepZen endpoint is setup with a StepZen folder made in the root of our project. Let's go into a little more detail on this folder's structure.

.
├── stepzen
   ├── airtable.graphql
   ├── lob.graphql
   ├── index.graphql
   ├── config.yaml
   └── stepzen.config.json

Here, airtable.graphql and lob.graphql contain the types, queries, and mutations that define our graphql schemas. We'll go into more detail on what they look like in the next couple of sections.

index.graphql contains the airtable.graphql and lob.graphql schemas:

schema @sdl(files: ["airtable.graphql", "lob.graphql"]) {
  query: Query
}

Basically, it tells StepZen which schemas to make available on the StepZen endpoint, by naming them within files: [...].

config.yaml contains the configuration details for the APIs so StepZen can access them. In this case the details we provide are:

configurationset:
  - configuration:
      name: airtable_config
      Authorization: Bearer KEY_HERE
      baseid: BASE_ID_HERE
  - configuration:
      name: lob_config
      Authorization: Basic KEY_HERE

Lastly, stepzen.config.json holds the name of our endpoint:

{
  "endpoint": "api/website"
}

Connecting to Lob

Our first query on our Stickers page will make a fetch call to Lob, an address verification API. Here's what it looks like in our lob.graphql schema.

This query goes to Lob, an address verification API. This ensures that the user is entering their address correctly. Here's what it looks like in our GraphQL schema:

type Mutation {
  """
  Send the address details
  to verify if the shipment
  will be deliverable.

  Equivalent To POST /v1/us_verifications
  """
  lob_us_verification(
    """
    The address
    """
    primary_line: String!
    """
    The city.
    """
    city: String!
    """
    The state in abbreviated format.
    """
    state: String!
    """
    The zipcode in 5 digit format.
    """
    zip_code: String!
  ): Lob_US_Verification
    @rest(
      method: POST
      contenttype: "application/x-www-form-urlencoded"
      endpoint: "https://api.lob.com/v1/us_verifications"
      configuration: "lob_config"
    )
}

You can see that we're using the custom StepZen directive @rest to post to the endpoint, specifying:

  • method - the method that the http request will use
  • contenttype - the content type of the mutation
  • endpoint - the endpoint the directive connects to
  • configuration - the name of the configuration keys etc in config.yaml

This sets defines the mutation so if we run:

mutation MyMutation {
  lob_us_verification(
    city: "Washington"
    primary_line: "1600 Pennsylvania Avenue, N.W."
    state: "D.C."
    zip_code: "20500"
  ) {
    id
    deliverability
  }
}

Then we get an id and deliverability confirming verification:

{
  "data": {
    "lob_us_verification": {
      "id": "us_ver_f527198c03e7480e9ff9"
      "deliverability": "deliverable"
    }
  }
}

Connecting to Airtable

Once the address has been verified by the Lob API, it can be stored in Airtable.

The mutation StepZen used to log the address information into Airtable looks like:

type Mutation {
  createShipment(
    firstname: String!
    lastname: String!
    address: String!
    apartment: String!
    city: String!
    state: String!
    zip: String!
  ): Airtable_Shipment
    @rest(
      method: POST
      resultroot: "records[]"
      postbody: "{\"records\":[{\"fields\":{\"firstname\":\"{{.Get \"firstname\" }}\",\"lastname\":\"{{.Get \"lastname\" }}\",\"address\":\"{{.Get \"address\" }}\",\"apartment\":\"{{.Get \"apartment\" }}\",\"city\":\"{{.Get \"city\" }}\",\"state\":\"{{.Get \"state\" }}\",\"zip\":\"{{.Get \"zip\" }}\"}}]}"
      endpoint: "https://api.airtable.com/v0/$baseid/Addresses"
      configuration: "airtable_config"
    )
}

Here, @rest defines the

  • method - the method that the http request will use
  • resultroot - this defines the top layer of json so StepZen can 'peel' it off and you don't have to specify 'records' in your query.
  • postbody - the information held in the postbody
  • configuration - the name of the configuration keys etc in config.yaml

This defines the Airtable mutation so you can send:

mutation MyMutation {
  createShipment(
    address: "1600 Pennsylvania Avenue, N.W."
    apartment: ""
    city: "Washington"
    firstname: "Joe"
    lastname: "Biden"
    state: "D.C."
    zip: "20500"
  ) {
    createdTime
    id
  }
}

and see the address in Airtable!

Conclusion

After defining the schemas inside the StepZen folder, all it took were a couple axios calls in our API which used information from the frontend captured by Next.js, and our stickers page was live!

We enjoyed the process of using StepZen to make it, and we hope you enjoyed learning about it! Feel free to grab a sticker. :)