Overview
To begin putting the pieces of our GraphQL server together, we need to take a closer look at Schema Definition Language, or SDL. This is the syntax that lets us actually define object types and their fields in a way that the GraphQL server can understand.
In this lesson, we will:
- Explore SDL syntax
- Define a basic schema with a
Query
and aPlaylist
type - Add our dependencies
📄 Exploring SDL
You can think of our server's schema as a contract between the server and any client asking for data. It defines what a GraphQL API can and can't do, and how clients can request or change data. It's an abstraction layer that provides flexibility to consumers while hiding backend implementation details.
In practice, a schema is a collection of object types that contain fields. Each field has a type of its own. A field's type can be scalar (such as an Int
or a String
), or it can be another object type. We'll see an example of this shortly.
GraphQL type syntax
We declare a type using the type
keyword, followed by the name of the type (PascalCase is best practice), then opening brackets to hold its fields:
type Artist {}
Fields are declared by their name (camelCase), a colon, and then the type of the field (scalar or object). A field can also contain a list, indicated by square brackets:
type Artist {id: IDname: StringbirthYear: IntalbumNames: [String]}
Nullability in GraphQL
In addition, we can indicate whether each field value is nullable or non-nullable. If a field should never be null, we add an exclamation mark after its type:
type Artist {id: ID!name: String!birthYear: IntalbumNames: [String]}
This syntax states that it's not valid for an Artist
to return null
for the id
or name
fields; we require them to return a value that matches their specified data type. By contrast, we'll permit birthYear
and albumNames
to be null
if we have no data to return.
Working with multiple object types
The initial schema we define isn't rigid, or locked in place—GraphQL gives us the flexibility to add more types and fields as time goes on, further enhancing the data capabilities of our API. Take these two object types for example:
type Artist {id: ID!name: String!birthYear: Int}type RecordLabel {id: ID!name: String!yearFounded: Int}
Suppose we want to represent an artist as belonging to a particular record label. How do we represent this in GraphQL?
In this case, we'd update Artist
with a field that returns another object type; one that specifies which record label it belongs to.
type Artist {id: ID!name: String!birthYear: IntsignedTo: RecordLabel}type RecordLabel {id: ID!name: String!yearFounded: Int}
This relationship lets us query details about an artist, then query further details about the record label they're signed to. We can ask more complex questions of our data—like "When were each of these artists born, and what are the names of the record labels they're each signed to?"—and get all of the answers in one neatly-bundled response.
Documenting the schema
All right, last thing before we start writing our schema: descriptions.
It's good practice to document your schema, in the same way that it's helpful to comment your code. It makes it easier for your teammates (and future you) to make sense of what's going on. It also allows tools like the Apollo Studio Explorer to guide API consumers on what they can achieve with your API right when and where they need it.
To do that, the SDL lets you add descriptions to both types and fields by writing strings (in quotation marks) directly above them.
"I'm a regular description"
Triple "double quotes" allow you to add line breaks for clearer formatting of lengthier comments.
"""I'm a block descriptionwith a line break"""
Here's what a fully-documented GraphQL type might look like.
"Catalog information for a single artist."type Artist {"The ID for the artist"id: ID!"The artist's name"name: String!"The year (YYYY format) the artist was born"birthYear: Int"The particular record label the artist is signed with"signedTo: RecordLabel}
With that final point covered, let's build our schema!
Building the schema
Let's navigate to the src
directory. In there, we're going to create a new file called schema.graphql
.
📂 src┣ 📄 graphql.d.ts┣ 📄 index.ts┗ 📄 schema.graphql
✏️ Let's define that schema
Referring back to our mockup, we identified that we need some data for each playlist.
For this course, we're going to skip the playlist image and tackle a pared-down version of the mockup. So let's focus on these two basic fields:
name
description
We'll also need a field that we can use to differentiate one playlist from another—we'll give this field the name id
.
With our three fields of id
, name
, and description
, let's bring the Playlist
type to life!
The Playlist
type
Let's define the Playlist
type in our schema.graphql
file.
"A curated collection of tracks designed for a specific activity or mood."type Playlist {# Fields go here}
Now for the playlist's fields, we'll have:
id
of typeID!
name
of typeString!
description
of typeString
So we should end up with a Playlist
type that looks like this:
"A curated collection of tracks designed for a specific activity or mood."type Playlist {"The ID for the playlist."id: ID!"The name of the playlist."name: String!"Describes the playlist, what to expect and entices the user to listen."description: String}
The Playlist
type is complete for now, but we need a way to actually ask for playlist data from our GraphQL server. For that, we have a separate Query
type.
Not seeing the nice GraphQL syntax highlighting you want? Check out the GraphQL: Syntax Highlighting extension for VS Code.
The Query
type
The Query
type is defined like any other object type. We'll add it just above the Playlist
type.
type Query {# Fields go here}"A curated collection of tracks designed for a specific activity or mood."type Playlist {"The ID for the playlist."id: ID!"The name of the playlist."name: String!"Describes the playlist, what to expect and entices the user to listen."description: String}
The fields of this type are entry points into the rest of our schema. These are the top-level fields that our client can query for.
For now, we're only interested in fetching the list of featured playlists for our homepage. Let's name the field featuredPlaylists
to make it as descriptive as possible. We want this field to return a list of Playlist
s. We'll also add a nice description:
type Query {"Playlists hand-picked to be featured to all users."featuredPlaylists: [Playlist!]!}
Our schema is now fully defined to support our first feature!
Practice
Query
type?Key takeaways
- The fields of the
Query
type are entry points into our schema. These are the top-level fields that a GraphQL consumer can query for. - GraphQL object types define fields we can query for data. These fields can return scalar data (such as
String
orInt
) or return other object types.
Up next
Now that our base schema is ready, we can start working on the next piece of our API—the server!
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.