Slide 1

Slide 1 text

Getting Started with GraphQL And Atlas @JoeKarlsson1

Slide 2

Slide 2 text

@JoeKarlsson1

Slide 3

Slide 3 text

@JoeKarlsson1

Slide 4

Slide 4 text

@JoeKarlsson1

Slide 5

Slide 5 text

{ name: “Joe Karlsson”, company: “MongoDB”, title: [ “Developer Advocate”, “Software Engineer” ], } twitter: “@JoeKarlsson1”, twitch: “joe_karlsson”, website: “joekarlsson.com”, opinions: “my own”, links: “bit.ly/GraphQLAtlas” bit.ly/ GraphQLAtlas

Slide 6

Slide 6 text

Before we get started… @JoeKarlsson1

Slide 7

Slide 7 text

Thank you for coming! @JoeKarlsson1

Slide 8

Slide 8 text

Who is this talk for? @JoeKarlsson1

Slide 9

Slide 9 text

@JoeKarlsson1

Slide 10

Slide 10 text

@JoeKarlsson1 A quick audience poll @JoeKarlsson1

Slide 11

Slide 11 text

GraphQL? @JoeKarlsson1

Slide 12

Slide 12 text

Want to follow along? @JoeKarlsson1 http://bit.ly/GraphQLAtlas

Slide 13

Slide 13 text

AGENDA @JoeKarlsson1 ‣ What is GraphQL? ‣ Apollo Client ‣ Making Queries ‣ Mutating Data

Slide 14

Slide 14 text

AGENDA @JoeKarlsson1 ‣ What is GraphQL? ‣ Apollo Client ‣ Making Queries ‣ Mutating Data

Slide 15

Slide 15 text

What Is GraphQL? @JoeKarlsson1

Slide 16

Slide 16 text

@JoeKarlsson1 MFW I first started learning GraphQL

Slide 17

Slide 17 text

Imagine This @JoeKarlsson1

Slide 18

Slide 18 text

GET /api/v2/user/{ID}/recent-orders @JoeKarlsson1 Endpoint Returns [0128, 7298, 6715, … ]

Slide 19

Slide 19 text

@JoeKarlsson1

Slide 20

Slide 20 text

We now need a hydrated list of orders @JoeKarlsson1

Slide 21

Slide 21 text

What’s the best way update our API? @JoeKarlsson1

Slide 22

Slide 22 text

GET /hydrated-recent-orders GET /hydrate-skus GET /recent-orders?hydrated=true @JoeKarlsson1 ???

Slide 23

Slide 23 text

REST GRAPHQL @JoeKarlsson1

Slide 24

Slide 24 text

Why Use GraphQL? @JoeKarlsson1

Slide 25

Slide 25 text

@JoeKarlsson1 Let’s jump in!

Slide 26

Slide 26 text

DECLARATIVE @JoeKarlsson1

Slide 27

Slide 27 text

@JoeKarlsson1

Slide 28

Slide 28 text

CAN USE MULTIPLE COLLECTIONS Users.Info IoT.Data Movies.Data @JoeKarlsson1

Slide 29

Slide 29 text

VALIDATED AND STRUCTURED @JoeKarlsson1

Slide 30

Slide 30 text

@JoeKarlsson1 Control the shape and content of your documents {
 "properties": {
 "_id": {
 "bsonType": "objectId"
 },
 "description": {
 "bsonType": "string"
 },
 "imageUrl": {
 "bsonType": "string"
 }
 }
 }

Slide 31

Slide 31 text

@JoeKarlsson1

Slide 32

Slide 32 text

FACILITATES COLLABORATION @JoeKarlsson1

Slide 33

Slide 33 text

UNIFIES ALL API ENDPOINTS @JoeKarlsson1

Slide 34

Slide 34 text

NO MORE API VERSIONING @JoeKarlsson1

Slide 35

Slide 35 text

NO MORE WRITING DOCUMENTATION @JoeKarlsson1

Slide 36

Slide 36 text

GraphiQL @JoeKarlsson1 One of my favorite features of GraphQL…

Slide 37

Slide 37 text

@JoeKarlsson1

Slide 38

Slide 38 text

GRAPHQL IS NOT A REPLACEMENT FOR COMMUNICATION @JoeKarlsson1

Slide 39

Slide 39 text

*SUPER FAST @JoeKarlsson1

Slide 40

Slide 40 text

@JoeKarlsson1 NO MORE OVER FETCHING

Slide 41

Slide 41 text

@JoeKarlsson1 WHAT I NEEDED { "name": "Joe Karlsson", "company": "MongoDB", "title": [ "Developer Advocate", "Software Engineer" ] } GET /api/user/JoeKarlsson

Slide 42

Slide 42 text

@JoeKarlsson1 vs. What I got

Slide 43

Slide 43 text

@JoeKarlsson1 NO MORE MULTIPLE ROUNDTRIPS

Slide 44

Slide 44 text

*ABSTRACTION ALWAYS ADDS A PERFORMANCE COST @JoeKarlsson1

Slide 45

Slide 45 text

GraphQL makes working with data easy @JoeKarlsson1

Slide 46

Slide 46 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL?

Slide 47

Slide 47 text

@JoeKarlsson1 ‣ REST vs GraphQL REST GRAPHQL Getting Started with GraphQL ‣ What is GraphQL?

Slide 48

Slide 48 text

@JoeKarlsson1 ‣ What is GraphQL? ‣ REST vs GraphQL ‣ Why use GraphQL? ‣ Declarative Getting Started with GraphQL

Slide 49

Slide 49 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Declarative Getting Started with GraphQL ‣ Why use GraphQL? ‣ Validated and structured ‣ What is GraphQL? {
 "properties": {
 "_id": {
 "bsonType": "objectId"
 },
 "description": {
 "bsonType": "string"
 },
 "imageUrl": {
 "bsonType": "string"
 }
 }
 }

Slide 50

Slide 50 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL?

Slide 51

Slide 51 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL? ‣ NO MORE WRITING DOCUMENTATION

Slide 52

Slide 52 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL? ‣ NO MORE WRITING DOCUMENTATION ‣ NO MORE API VERSIONING

Slide 53

Slide 53 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ What is GraphQL? ‣ Makes working with data easy

Slide 54

Slide 54 text

AGENDA @JoeKarlsson1 ‣ What is GraphQL? ‣ Apollo Client ‣ Making Queries ‣ Mutating Data

Slide 55

Slide 55 text

Let’s checkout something practical @JoeKarlsson1 bit.ly/ GraphQLAtlas

Slide 56

Slide 56 text

@JoeKarlsson1

Slide 57

Slide 57 text

Cloud Client MongoDB Atlas GraphQL Apollo Client React @JoeKarlsson1 +

Slide 58

Slide 58 text

A Brief Intro to Apollo @JoeKarlsson1

Slide 59

Slide 59 text

UI COMPONENTS GraphQL Query Requests Data Sends Result Updates UI @JoeKarlsson1

Slide 60

Slide 60 text

@JoeKarlsson1 MAKES WORKING WITH GRAPHQL MUCH EASIER

Slide 61

Slide 61 text

import { HttpLink, InMemoryCache, ApolloClient } from 'apollo-boost'; import { setContext } from 'apollo-link-context'; import CONFIG from '../config'; // Add an Authorization header to each GraphQL request const authLink = setContext((_, { headers }) => ({ headers: { ...headers, Authorization: `Bearer ${CONFIG.accessToken}`, }, })); // Connect Apollo to the GraphQL Endpoint const GRAPHQL_URL = `https://stitch.mongodb.com/api/client/v2.0/app/${STICH_APP_ID}/graphql`; const httpLink = new HttpLink({ uri: GRAPHQL_URL }); // Instantiate the Apollo Client const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), }); Setup Apollo with GraphQL and Atlas

Slide 62

Slide 62 text

Connect Apollo to React Provider function InstaPostApp() { return ( ); } import { HttpLink, InMemoryCache, ApolloClient } from 'apollo-boost'; import { setContext } from 'apollo-link-context'; import CONFIG from '../config'; // Add an Authorization header to each GraphQL request const authLink = setContext((_, { headers }) => ({ headers: { ...headers, Authorization: `Bearer ${CONFIG.accessToken}`, }, })); // Connect Apollo to the GraphQL Endpoint const GRAPHQL_URL = `https://stitch.mongodb.com/api/client/v2.0/app/${STICH_APP_ID}/graphql`; const httpLink = new HttpLink({ uri: GRAPHQL_URL }); // Instantiate the Apollo Client const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), }); import React, { Fragment } from 'react'; import { ApolloProvider } from '@apollo/react-hooks';

Slide 63

Slide 63 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo?

Slide 64

Slide 64 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts + +

Slide 65

Slide 65 text

@JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? Getting Started with GraphQL

Slide 66

Slide 66 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? ‣ Setup Apollo with GraphQL and Atlas // Connect Apollo to the GraphQL Endpoint const GRAPHQL_URL = `https://stitch.mongodb.com/api/client/v2.0/app/${STICH_APP_ID}/graphql`; const httpLink = new HttpLink({ uri: GRAPHQL_URL }); // Instantiate the Apollo Client const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), });

Slide 67

Slide 67 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? ‣ Setup Apollo with GraphQL and Atlas function InstaPostApp() { return ( ); } ‣ Connected Apollo to React

Slide 68

Slide 68 text

AGENDA @JoeKarlsson1 ‣ What is GraphQL? ‣ Apollo Client ‣ Efficient Queries ‣ Mutating Data

Slide 69

Slide 69 text

@JoeKarlsson1 MONGODB AUTOMATICALLY GENERATES YOUR QUERIES BASED ON YOUR SCHEMA

Slide 70

Slide 70 text

@JoeKarlsson1

Slide 71

Slide 71 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL QUERY query { } 1) Is this a Query or a Mutation?

Slide 72

Slide 72 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL QUERY query { } instaposts { } 2) What do you want to query?

Slide 73

Slide 73 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL QUERY query { } instaposts { } 3) What data do you want? _id description imageUrl

Slide 74

Slide 74 text

Querying GraphQL with Apollo and React import React, { Fragment } from 'react'; import { useQuery } from '@apollo/react-hooks'; import gql from 'graphql-tag'; import ListPage from './ListPage'; const FIND_ALL_INSTAPOSTS = gql` query { instaposts { _id description imageUrl } } `; function ListPageContainer(props) { const { loading, error, data } = useQuery(FIND_ALL_INSTAPOSTS, { pollInterval: 500, }); } export default ListPageContainer; return ( {loading &&
Loading…
} {error &&
{`encountered an error: ${error}`}
} {data && } );

Slide 75

Slide 75 text

@JoeKarlsson1

Slide 76

Slide 76 text

@JoeKarlsson1

Slide 77

Slide 77 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries

Slide 78

Slide 78 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries

Slide 79

Slide 79 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries ‣ How to construct a GraphQL query query { instaposts { _id description imageUrl } } Query or a Mutation? What do you want to query? What data do you want?

Slide 80

Slide 80 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries ‣ How to construct a GraphQL query ‣ Querying GraphQL with Apollo and React function ListPageContainer(props) { const { loading, error, data } = useQuery(FIND_ALL_INSTAPOSTS, { pollInterval: 500, }); return ( {loading &&
Loading…
} {error &&
{`encountered an error: ${error}`}
} {data && } ); }

Slide 81

Slide 81 text

AGENDA @JoeKarlsson1 ‣ What is GraphQL? ‣ Apollo Client ‣ Making Queries ‣ Mutating Data

Slide 82

Slide 82 text

mutation ( ) { } @JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION Is this a Query or a Mutation?

Slide 83

Slide 83 text

mutation ( ) { } @JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION Operation name describes the GraphQL String CreatePostMutation

Slide 84

Slide 84 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION mutation CreatePostMutation( ) { } Arguments allow you to pass data to fields $data: InstapostInsertInput! Argument Type. This is defined by the GraphQl server

Slide 85

Slide 85 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION mutation CreatePostMutation( ) { } $data: InstapostInsertInput! Bang - This means the argument is required.

Slide 86

Slide 86 text

mutation CreatePostMutation( ) { } insertOneInstapost (data: $data) { } @JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION Mutation type. This is defined by the GraphQl server $data: InstapostInsertInput! Arguments

Slide 87

Slide 87 text

insertOneInstapost (data: $data) { } @JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION mutation CreatePostMutation( ) { } What data do you returned, once the data has been mutated? $data: InstapostInsertInput! _id description imageUrl

Slide 88

Slide 88 text

@JoeKarlsson1 CONSTRUCTING A GRAPHQL MUTATION mutation CreatePostMutation($data: InstapostInsertInput!) { insertOneInstapost(data: $data) { _id description imageUrl } } Query or a Mutation? Operation name Arguments Mutation Type What data do you want?

Slide 89

Slide 89 text

GraphQL Mutations with Apollo and React function CreatePage(props) { let imageUrl = { value: '' }; let description = ''; const [addPost] = useMutation(ADD_INSTAPOST); return ( ); } import React from 'react'; import { useMutation } from '@apollo/react-hooks'; import gql from 'graphql-tag'; // CreatePage.js const ADD_INSTAPOST = gql` mutation CreatePostMutation($data: InstapostInsertInput!) { insertOneInstapost(data: $data) { _id description imageUrl } } `; { e.preventDefault(); // Invoke the mutation method // and pass in the required variables addPost({ variables: { data: { description: description.value, imageUrl: imageUrl.value, }, }, }); }} > { imageUrl = url; }} /> { description = str; }} /> Post

Slide 90

Slide 90 text

@JoeKarlsson1

Slide 91

Slide 91 text

@JoeKarlsson1

Slide 92

Slide 92 text

Do you want to learn GraphQL? @JoeKarlsson1

Slide 93

Slide 93 text

@JoeKarlsson1

Slide 94

Slide 94 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL?

Slide 95

Slide 95 text

@JoeKarlsson1 ‣ REST vs GraphQL REST GRAPHQL Getting Started with GraphQL ‣ What is GraphQL?

Slide 96

Slide 96 text

@JoeKarlsson1 ‣ What is GraphQL? Getting Started with GraphQL ‣ REST vs GraphQL ‣ Why use GraphQL?

Slide 97

Slide 97 text

@JoeKarlsson1 ‣ What is GraphQL? ‣ REST vs GraphQL ‣ Why use GraphQL? ‣ Declarative Getting Started with GraphQL

Slide 98

Slide 98 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Declarative Getting Started with GraphQL ‣ Why use GraphQL? ‣ Validated and structured ‣ What is GraphQL? {
 "properties": {
 "_id": {
 "bsonType": "objectId"
 },
 "description": {
 "bsonType": "string"
 },
 "imageUrl": {
 "bsonType": "string"
 }
 }
 }

Slide 99

Slide 99 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL?

Slide 100

Slide 100 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL? ‣ NO MORE WRITING DOCUMENTATION

Slide 101

Slide 101 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ UNIFIES ALL API ENDPOINTS ‣ What is GraphQL? ‣ NO MORE WRITING DOCUMENTATION ‣ NO MORE API VERSIONING

Slide 102

Slide 102 text

@JoeKarlsson1 ‣ REST vs GraphQL ‣ Validated and structured ‣ Facilitates Collaboration Getting Started with GraphQL ‣ Why use GraphQL? ‣ Declarative ‣ What is GraphQL? ‣ Makes working with data easy

Slide 103

Slide 103 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo?

Slide 104

Slide 104 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts + +

Slide 105

Slide 105 text

@JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? Getting Started with GraphQL

Slide 106

Slide 106 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? ‣ Setup Apollo with GraphQL and Atlas // Connect Apollo to the GraphQL Endpoint const GRAPHQL_URL = `https://stitch.mongodb.com/api/client/v2.0/app/${STICH_APP_ID}/graphql`; const httpLink = new HttpLink({ uri: GRAPHQL_URL }); // Instantiate the Apollo Client const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), });

Slide 107

Slide 107 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Introduced InstaPosts ‣ How does Apollo work? ‣ Setup Apollo with GraphQL and Atlas function InstaPostApp() { return ( ); } ‣ Connected Apollo to React

Slide 108

Slide 108 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries

Slide 109

Slide 109 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries

Slide 110

Slide 110 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries ‣ How to construct a GraphQL query query { instaposts { _id description imageUrl } } Query or a Mutation? What do you want to query? What data do you want?

Slide 111

Slide 111 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ MongoDB automatically generates the queries ‣ How to construct a GraphQL query ‣ Querying GraphQL with Apollo and React function ListPageContainer(props) { const { loading, error, data } = useQuery(FIND_ALL_INSTAPOSTS, { pollInterval: 500, }); return ( {loading &&
Loading…
} {error &&
{`encountered an error: ${error}`}
} {data && } ); }

Slide 112

Slide 112 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ Mutating data with GraphQL

Slide 113

Slide 113 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ Mutating data with GraphQL ‣ Constructing a GraphQL Mutation mutation CreatePostMutation($data: InstapostInsertInput!) { insertOneInstapost(data: $data) { _id description imageUrl } } Query or a Mutation? Operation name Arguments Mutation Type What data do you want?

Slide 114

Slide 114 text

Getting Started with GraphQL @JoeKarlsson1 ‣ What is GraphQL? ‣ What is Apollo? ‣ Making effective queries ‣ Mutating data with GraphQL ‣ Constructing a GraphQL Mutation ‣ GraphQL mutations with Apollo and React function CreatePage(props) { let imageUrl = { value: '' }; let description = ''; const [addPost] = useMutation(ADD_INSTAPOST); return ( { e.preventDefault(); addPost({ variables: { data: { description: description.value, imageUrl: imageUrl.value, }, }, }); }} > { imageUrl = url; }} /> { description = str; }} /> Post ); }

Slide 115

Slide 115 text

@JoeKarlsson1 Questions?

Slide 116

Slide 116 text

All resources and links used in this talk can be found here: @JoeKarlsson1 bit.ly/GraphQLAtlas

Slide 117

Slide 117 text

Want $200 in free Atlas credits? @JoeKarlsson1 Use code JOEKARLSSON200 http://bit.ly/JoeKMDBSF

Slide 118

Slide 118 text

Do you have feedback about this talk? @JoeKarlsson1 bit.ly/GraphQLAtlas

Slide 119

Slide 119 text

THANK YOU! @JoeKarlsson1

Slide 120

Slide 120 text

{ name: “Joe Karlsson”, company: “MongoDB”, title: [ “Developer Advocate”, “Software Engineer” ], twitter: “@JoeKarlsson1”, twitch: “joe_karlsson”, website: “joekarlsson.com”, links: “bit.ly/GraphQLAtlas” } bit.ly/ GraphQLAtlas

Slide 121

Slide 121 text

Addtional Resources ‣Link to all resources: bit.ly/GraphQLAtlas ‣Source Code: github.com/JoeKarlsson/mongodb-graphql-demo ‣GraphQL Official Docs: graphql.org ‣GraphQL Hub: graphqlhub.com ‣Apollo Official Docs: apollographql.com @JoeKarlsson1 bit.ly/GraphQLAtlas

Slide 122

Slide 122 text

@JoeKarlsson1