Build a GraphQL API with Apollo Server
Build a GraphQL API for a game library using Apollo Server 5.
Introduction
30 Second Summary
When you use an app that loads exactly the information you need without wasting time on data you didn't ask for, there's often a GraphQL API behind the scenes making that possible.
In this project, you will build a GraphQL API from scratch using Apollo Server and Node.js. Your API will let clients query a game library and add new games to it.
What You'll Build
A locally running GraphQL API for a game library tracker, powered by Apollo Server 5 and tested interactively via Apollo Sandbox in the browser.
By the end of this project, you'll have:
- A Node.js project with Apollo Server 5 configured and running locally.
- A GraphQL schema with custom types, queries, and mutations written in Schema Definition Language.
- Working resolvers that handle data fetching and creation logic, tested via Apollo Sandbox in the browser.
- Secret Mission: Add query filtering and an update mutation for more advanced data operations.
Are there any prerequisites?
You should have basic JavaScript familiarity (variables, functions, arrays, and objects). No prior GraphQL or backend experience is needed.
Set Up Your Project
To build a GraphQL API, you need a JavaScript runtime and a few packages. Node.js runs your server code outside the browser, and Apollo Server provides the GraphQL framework that handles queries and mutations.
In this step, you will install Node.js, create a project folder, and install the Apollo Server dependencies your API needs.
In this step, get ready to:
- Install and verify Node.js v20 or higher.
- Create and initialize the game-library-api project folder.
- Install Apollo Server and GraphQL packages.
Install Node.js
Apollo Server 5 requires Node.js version 20 or higher. Let's confirm yours is ready.
- Open your terminal by pressing Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or Command Prompt (Windows) and press Enter to open it.
- Check your Node.js version by running this command:
node -v
Look at the version number printed in your terminal.
✔️ I see version 20 or higher
If you see v20.x.x, v22.x.x, v24.x.x, or any number 20 or above, you are good to go. Move on to the next substep.
ⓧ I see a version lower than 20
You have Node.js installed, but it is too old for Apollo Server 5. You need to upgrade to version 20 or higher.
- Visit https://nodejs.org and download the LTS installer for your operating system.
- Run the installer and accept the default options. It will upgrade your existing Node.js installation.
- Close and reopen your terminal, then run node -v again to confirm the version is now 20 or higher.
ⓧ Command not found
Node.js is not installed on your machine yet.
- Visit https://nodejs.org and download the LTS installer for your operating system.
- Run the installer and accept the default options.
- Close and reopen your terminal, then run node -v again to confirm the version is 20 or higher.
What is Node.js?
Node.js is a JavaScript runtime that lets you run JavaScript code on your computer, outside of a web browser. Every package and server in this project runs on Node.js.
Create your project folder and initialize it
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir game-library-api
cd game-library-api
- Confirm the folder exists by running:
ls ~/Desktop
You should see game-library-api listed in the output.
- Open game-library-api in VS Code by pressing Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code and press Enter to open it.
- In VS Code, click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the game-library-api folder, and click Open.
You should see the empty game-library-api folder open in VS Code's Explorer sidebar.
- Open VS Code's built-in terminal by pressing Ctrl+` (backtick key, same on macOS and Windows).
- Initialize your project with ES Modules enabled by running this command:
npm init --yes && npm pkg set type="module"
What does this command do?
The npm init --yes part creates a package.json file with default values. This file tracks your project's name, version, and dependencies.
The npm pkg set type="module" part enables ES Modules, which lets you use modern import syntax instead of the older require() style.
- Confirm package.json was created by running:
ls
You should see package.json listed in the output.
Not seeing package.json?
Make sure you ran the command inside the game-library-api folder. Run pwd (macOS/Linux) or cd (Windows) to check your current directory. If you are not inside game-library-api, run cd ~/Desktop/game-library-api and try again.
help me troubleshoot why npm init is not working in my terminal
Install dependencies and create the entry file
Your project needs two packages: @apollo/server (the GraphQL server framework) and graphql (the core GraphQL implementation for JavaScript).
- Install both packages by running this command:
npm install @apollo/server graphql
You should see output showing the packages being downloaded and added to your project. A node_modules folder and package-lock.json file appear in the Explorer sidebar.
Seeing permission errors or network failures?
If you see EACCES permission errors on macOS/Linux, try prefixing the command with sudo. If you see network errors, check your internet connection and try again.
help me fix npm install errors for @apollo/server and graphql
- Create the entry file for your project. In VS Code's Explorer sidebar, hover over the GAME-LIBRARY-API heading area.
- Click the New File icon (a page with a plus sign).
- Type index.js and press Enter.
The file opens as an empty tab in the editor. Leave it empty for now.
- Add a start script to your package.json by running this command in the terminal:
npm pkg set scripts.start="node index.js"
What does this command do?
This adds a start script to your package.json that runs node index.js. Now when you type npm start, Node.js will execute your index.js file.
- Verify everything works by running:
npm start
The command should exit cleanly with no errors. Since index.js is empty, it simply finishes and returns you to the terminal prompt.
Seeing an error when running npm start?
If you see a "Missing script: start" error, the npm pkg set command may not have saved correctly. Open package.json in VS Code and check that the "scripts" section contains "start": "node index.js".
If you see "Cannot find module", make sure index.js exists in the same folder as package.json. Run ls to confirm both files are listed.
help me fix the npm start error in my game-library-api project
✔️ Awesome, I've got everything!
Great. Double check that you have saved all your files, then move on to the next step.
ⓧ I'd like to double check the full code
Here is what your package.json should look like at this point:
{
"name": "game-library-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@apollo/server": "^5.5.1",
"graphql": "^16.14.2"
}
}
Your index.js file should exist and be completely empty. Minor differences in your package.json (like an extra test script from npm init) are fine and will not affect your project.
Your project skeleton is ready with all the dependencies installed. Next up, you will write your first GraphQL schema and define the data types for your game library.
Define Your GraphQL Schema
Your project is initialized and your dependencies are installed. Now it's time to define the blueprint that tells your API what data exists and how clients can ask for it.
In GraphQL, this blueprint is called a schema. The schema describes every type of data your API can return, and every query a client can run. You'll write yours using GraphQL's Schema Definition Language (SDL).
In this step, get ready to:
- Define a Game type and Query type in your GraphQL schema.
- Add sample game data for your API to serve.
Add imports and define your schema types
A GraphQL schema is where you declare the shape of your data and the operations clients can perform. You'll define two types: a Game type describing each game's fields, and a Query type listing the ways clients can fetch data.
- In VS Code, open index.js from the Explorer sidebar.
- Paste the following code into the file:
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// Schema definition
const typeDefs = `#graphql
type Game {
id: ID!
title: String!
platform: String!
year: Int
completed: Boolean!
}
type Query {
games: [Game!]!
game(id: ID!): Game
}
`;
What does this code do?
The two import lines pull in Apollo Server (the GraphQL server library) and a helper to start it as a standalone HTTP server. You'll use both in the next step.
The typeDefs variable holds your entire schema. The #graphql tag at the top enables syntax highlighting in VS Code if you have the Apollo GraphQL extension installed.
- The Game type describes each game's fields. The ! after a type means the field is required (non-null). year has no ! because not every game needs a year listed.
- The Query type defines what clients can ask for. games returns a list of all games. game(id: ID!) looks up a single game by its ID.
- [Game!]! means the query always returns a non-null list, and every item in that list is a non-null Game. The single game query returns Game without a ! because it can return null if no matching game exists.
Why schema-first over code-first?
There are two ways to define a GraphQL schema. Schema-first (SDL) lets you write the schema in GraphQL's own language, which maps directly to the concepts you're learning. Code-first tools generate the schema from your programming language's type system.
Schema-first is the better starting point because you see exactly what your API looks like from the client's perspective. Once you're comfortable with the concepts, code-first becomes a productivity boost.
You won't see a change yet. The next chunk adds the sample data this schema will serve.
Add sample game data
Your schema defines the shape of the data, but you also need actual data for your API to return. You'll add a hardcoded array of game objects that matches the Game type you just defined.
- In index.js, add the following code below the closing `; of your typeDefs variable:
// Sample data
const games = [
{
id: '1',
title: 'The Legend of Zelda: Tears of the Kingdom',
platform: 'Nintendo Switch',
year: 2023,
completed: true,
},
{
id: '2',
title: 'Elden Ring',
platform: 'PC',
year: 2022,
completed: false,
},
{
id: '3',
title: 'God of War Ragnarok',
platform: 'PlayStation 5',
year: 2022,
completed: true,
},
{
id: '4',
title: 'Halo Infinite',
platform: 'Xbox Series X',
year: 2021,
completed: false,
},
];
What does this code do?
The games array holds four game objects, each matching the Game type from your schema. Notice how each object has an id, title, platform, year, and completed field.
This is in-memory data. It lives only while the server runs. In a production app you'd connect to a database, but hardcoded data keeps things simple while you focus on GraphQL itself.
- Save index.js.
- Open your terminal in VS Code by pressing Ctrl+` (macOS and Windows).
- Verify the file runs without errors by running:
npm start
- The script should exit cleanly with no output and no errors. This confirms your imports resolve correctly and your JavaScript has no syntax mistakes.
Seeing a SyntaxError or module error?
- If you see a message about Cannot use import statement outside a module, check that your package.json contains "type": "module". This tells Node.js to treat your files as ES Modules.
- If you see a SyntaxError pointing at the template literal, make sure the opening backtick (`) and closing backtick are both present. Template literals use backticks, not single or double quotes.
- If you see a module not found error for @apollo/server, make sure you ran npm install in the previous step and that your terminal is inside the game-library-api folder.
Why is my index.js throwing an error when I run npm start?
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here's the full index.js so far:
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// Schema definition
const typeDefs = `#graphql
type Game {
id: ID!
title: String!
platform: String!
year: Int
completed: Boolean!
}
type Query {
games: [Game!]!
game(id: ID!): Game
}
`;
// Sample data
const games = [
{
id: '1',
title: 'The Legend of Zelda: Tears of the Kingdom',
platform: 'Nintendo Switch',
year: 2023,
completed: true,
},
{
id: '2',
title: 'Elden Ring',
platform: 'PC',
year: 2022,
completed: false,
},
{
id: '3',
title: 'God of War Ragnarok',
platform: 'PlayStation 5',
year: 2022,
completed: true,
},
{
id: '4',
title: 'Halo Infinite',
platform: 'Xbox Series X',
year: 2021,
completed: false,
},
];
Your schema and data are ready. Next up, you'll write resolvers that connect the schema to the data and start your server so you can actually query it.
Build Resolvers and Start the Server
Your schema defines what data your API can return. Now you need to tell the server how to actually fetch that data.
In GraphQL, the functions that handle data fetching are called resolvers. Each field in your schema maps to a resolver function that knows where to find the data. In this step, you will write those resolvers and launch the server so you can interact with your API.
In this step, get ready to:
- Write resolver functions for your queries.
- Create and start an Apollo Server instance.
- Open Apollo Sandbox in your browser to test your API.
Define the resolvers
A resolver is a function that returns data for a specific field in your schema. Your Query type has two fields (games and game), so you need two resolver functions.
- In index.js, find the closing ]; of the games array at the bottom of the file.
- Add the following code below that line:
let nextId = 5;
// Resolvers
const resolvers = {
Query: {
games: () => games,
game: (parent, args) => games.find((game) => game.id === args.id),
},
};
What does this code do?
- games: () => games returns the entire games array whenever someone queries for all games.
- game: (parent, args) receives the arguments passed in the query. It uses args.id to search through the array and return the matching game.
- let nextId = 5 sets up a counter you will use later when adding new games.
What is a resolver?
Think of your schema as a menu and resolvers as the kitchen. The schema tells clients what they can order. The resolvers do the actual work of preparing and returning the data.
Every resolver receives four arguments: parent (the result of the parent resolver), args (the arguments passed in the query), context, and info. For now, you only need args.
- Save index.js.
Seeing a red underline or syntax error?
- Make sure the resolvers code is placed after the closing ]; of the games array, not inside it.
- Check that the arrow functions use => and not =< or ->.
- help me fix a syntax error in my resolvers
Create the server and start it
With your schema and resolvers ready, you can create an Apollo Server instance and launch it.
- Add the following code at the bottom of index.js, below the resolvers object:
// Server setup
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`Server ready at: ${url}`);
What does this code do?
- new ApolloServer({ typeDefs, resolvers }) creates a server instance that knows your schema and how to resolve each field.
- startStandaloneServer launches the server on port 4000 using Node's built-in HTTP server. No Express dependency needed.
- The await keyword means the code waits for the server to fully start before logging the URL to the console.
- Save index.js.
Seeing a warning about top-level await?
- Top-level await requires ES Modules. Check that your package.json contains "type": "module".
- Make sure you are running Node.js v20 or higher. Run node -v to check.
- help me fix a top-level await error in my Apollo Server project
Run the server and open Apollo Sandbox
- Start your server by running this command in the terminal:
npm start
- You should see this message in the terminal:
Server ready at: http://localhost:4000/
- Open http://localhost:4000 in your browser.
Apollo Sandbox loads automatically in the browser. You should see a code editor on the left and a response panel on the right. The schema explorer panel on the left side shows your Game type and your queries.
What is Apollo Sandbox?
Apollo Sandbox is a browser-based tool for testing your GraphQL API. It detects your schema automatically through introspection, so you can explore your types, write queries, and see responses without installing anything extra.
Server not starting?
- If you see an error about port 4000 being in use, another process is already running on that port. Close any other terminal sessions that may be running the server.
- If you see a module-not-found error, make sure you ran npm install in the game-library-api folder.
- help me troubleshoot why my Apollo Server won't start
✔️ Awesome, I've got everything!
Great. Double check you have saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the complete index.js file up to this point. Compare your code against it to find any differences.
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// Schema definition
const typeDefs = `#graphql
type Game {
id: ID!
title: String!
platform: String!
year: Int
completed: Boolean!
}
type Query {
games: [Game!]!
game(id: ID!): Game
}
`;
// Sample data
const games = [
{
id: '1',
title: 'The Legend of Zelda: Tears of the Kingdom',
platform: 'Nintendo Switch',
year: 2023,
completed: true,
},
{
id: '2',
title: 'Elden Ring',
platform: 'PC',
year: 2022,
completed: false,
},
{
id: '3',
title: 'God of War Ragnarok',
platform: 'PlayStation 5',
year: 2022,
completed: true,
},
{
id: '4',
title: 'Halo Infinite',
platform: 'Xbox Series X',
year: 2021,
completed: false,
},
];
let nextId = 5;
// Resolvers
const resolvers = {
Query: {
games: () => games,
game: (parent, args) => games.find((game) => game.id === args.id),
},
};
// Server setup
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`Server ready at: ${url}`);
Your API is live and Apollo Sandbox is ready to go. Next up, you will write your first queries and see how GraphQL lets you request exactly the fields you need.
Query Your API with Apollo Sandbox
Your GraphQL API is live and Apollo Sandbox is already connected to your schema. Now it's time to see GraphQL's main superpower in action: letting clients choose exactly which fields they want in a response.
In a traditional REST API, every endpoint returns a fixed shape of data. GraphQL flips this. You write a query that specifies only the fields you need, and the server responds with nothing more and nothing less.
In this step, get ready to:
- Query all games requesting only specific fields.
- Look up a single game by ID using a query variable.
- Explore the schema explorer to understand GraphQL introspection.
Query all games with field selection
The most powerful feature of GraphQL is field selection. You can request exactly the data you need and nothing extra. Let's prove this by querying your game library for only two fields.
- Switch back to Apollo Sandbox in your browser (the tab open at http://localhost:4000).
- Clear any existing query in the Operations panel (the middle section).
- Paste the following query into the Operations panel:
query GetGames {
games {
title
platform
}
}
- Click the blue play button in the upper right of the Operations panel to execute the query.
What does this query do?
This query asks your API for all games in the library, but only returns the title and platform fields. Your Game type also has id, year, and completed fields, but they won't appear in the response because you didn't ask for them.
This is GraphQL's key advantage over REST. A REST endpoint would return all fields every time, whether the client needs them or not.
In the Response panel on the right, you should see a JSON object containing only title and platform for each of your four games.
Not seeing any results?
Make sure your server is still running in the terminal. If you stopped it, run npm start again from the game-library-api folder.
Check that the query uses games (plural) and not game. The field names must match your schema exactly.
Help me debug why my GraphQL query isn't returning results in Apollo Sandbox.
Look up a single game by ID
Your schema also supports querying a single game by its ID. This uses a GraphQL variable to pass the ID value into the query dynamically.
- Clear the Operations panel and paste the following query:
query GetGame($id: ID!) {
game(id: $id) {
id
title
platform
year
completed
}
}
- Expand the Variables section at the bottom of the Operations panel.
- Paste the following JSON into the Variables section:
{
"id": "1"
}
- Click the blue play button to execute the query.
What are GraphQL variables?
The $ symbol indicates a variable in GraphQL. You declare it in the query signature ($id: ID!) and reference it in the query body (game(id: $id)). The actual value comes from the Variables section as JSON.
Variables let clients pass argument values dynamically without hardcoding them into the query string. This is how real applications send user input to a GraphQL API.
The Response panel should show all five fields for the game with ID 1 (The Legend of Zelda: Tears of the Kingdom).
- Now test what happens when a game doesn't exist. Change the variable value to an ID that isn't in your data:
{
"id": "99"
}
- Click the play button again.
The Response panel now shows null for the game field. This is the expected behavior because your game query returns a nullable Game type (no ! after it in the schema).
Explore the schema explorer
One of GraphQL's built-in strengths is that your API is self-documenting. Apollo Sandbox can read your entire schema through a feature called introspection.
- Click the schema exploration tab on the left side of Apollo Sandbox.
- Click into the Query type to see your games and game fields listed.
- Click into the Game type to see all five fields (id, title, platform, year, completed) with their types.
What is introspection?
Introspection is a built-in GraphQL feature that lets clients ask the server what types, fields, and operations are available. Apollo Sandbox uses introspection to populate the schema explorer and provide autocomplete suggestions as you type queries.
This means you never need separate API documentation. The schema IS the documentation, and any tool can read it automatically.
You now have hands-on experience with GraphQL's core querying features: field selection, arguments, variables, and introspection. Next up, you'll extend your API with mutations to add new games to the library.
Add Mutations to Modify Data
In the last step, you queried your API and saw how GraphQL lets clients pick exactly which fields they want back.
Queries are read-only operations. To let clients create, update, or delete data, your schema needs a Mutation type. In this step, you will add an addGame mutation so users can grow their game library through your API.
In this step, get ready to:
- Add a Mutation type to your GraphQL schema.
- Write a resolver that creates new game objects.
- Test the mutation in Apollo Sandbox and confirm new data persists.
Add the Mutation type to your schema
Your schema currently defines the Query type for reading data. Mutations follow the same SDL pattern but signal that the operation changes server-side state.
- In index.js, find the closing } of the type Query block inside your typeDefs string.
- Add the following Mutation type directly below it (still inside the template literal):
type Mutation {
addGame(title: String!, platform: String!, year: Int, completed: Boolean): Game!
}
What does this code do?
The Mutation type declares the write operations your API supports.
- addGame accepts four arguments. title and platform are required (!). year and completed are optional.
- The return type Game! guarantees the client always gets the newly created game back after a successful mutation.
- Save index.js.
Seeing a syntax error when you restart?
Make sure the type Mutation { ... } block sits inside the backtick-delimited template literal, not outside it. The closing backtick and semicolon should come after both Query and Mutation types.
Help me fix a syntax error in my typeDefs template literal.
Write the addGame resolver
A schema type without a matching resolver does nothing. The resolver contains the logic that actually creates a new game and stores it in your data.
- In index.js, find the resolvers object. Locate the closing }, of the Query property.
- Add a Mutation property directly after it by pasting the following code:
Mutation: {
addGame: (parent, args) => {
const newGame = {
id: String(nextId++),
title: args.title,
platform: args.platform,
year: args.year || null,
completed: args.completed || false,
};
games.push(newGame);
return newGame;
},
},
What does this code do?
The addGame resolver receives the mutation arguments through args.
- String(nextId++) generates a unique ID by incrementing the counter defined earlier in the file.
- Optional fields (year, completed) fall back to null or false if the client does not provide them.
- games.push(newGame) adds the game to the in-memory array so subsequent queries reflect the change.
- Save index.js.
- Stop the running server in your terminal by pressing Ctrl+C.
- Restart the server by running:
npm start
- You should see Server ready at: http://localhost:4000/ in your terminal again.
Server won't start?
Check that your resolvers object has a comma after the Query property's closing brace. The Mutation property must be a sibling of Query, not nested inside it.
Help me debug my resolvers object structure.
✔️ Awesome, I've got everything!
Great. Double check you have saved index.js and that your server restarted without errors.
ⓧ I'd like to double check the full code
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// Schema definition
const typeDefs = `#graphql
type Game {
id: ID!
title: String!
platform: String!
year: Int
completed: Boolean!
}
type Query {
games: [Game!]!
game(id: ID!): Game
}
type Mutation {
addGame(title: String!, platform: String!, year: Int, completed: Boolean): Game!
}
`;
// Sample data
const games = [
{
id: '1',
title: 'The Legend of Zelda: Tears of the Kingdom',
platform: 'Nintendo Switch',
year: 2023,
completed: true,
},
{
id: '2',
title: 'Elden Ring',
platform: 'PC',
year: 2022,
completed: false,
},
{
id: '3',
title: 'God of War Ragnarok',
platform: 'PlayStation 5',
year: 2022,
completed: true,
},
{
id: '4',
title: 'Halo Infinite',
platform: 'Xbox Series X',
year: 2021,
completed: false,
},
];
let nextId = 5;
// Resolvers
const resolvers = {
Query: {
games: () => games,
game: (parent, args) => games.find((game) => game.id === args.id),
},
Mutation: {
addGame: (parent, args) => {
const newGame = {
id: String(nextId++),
title: args.title,
platform: args.platform,
year: args.year || null,
completed: args.completed || false,
};
games.push(newGame);
return newGame;
},
},
};
// Server setup
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`Server ready at: ${url}`);
Test the addGame mutation in Apollo Sandbox
Your schema and resolver are wired up. Time to create a game and prove that your mutation works end-to-end.
- Switch back to Apollo Sandbox in your browser at http://localhost:4000.
- Clear the Operation panel and paste the following mutation:
mutation AddGame($title: String!, $platform: String!, $year: Int, $completed: Boolean) {
addGame(title: $title, platform: $platform, year: $year, completed: $completed) {
id
title
platform
year
completed
}
}
- In the **Variables** panel at the bottom of the Operation section, paste these values:
{
"title": "Hollow Knight: Silksong",
"platform": "Nintendo Switch",
"year": 2025,
"completed": false
}
- Click the blue play button to execute the mutation.
The Response panel should return a JSON object containing your new game with id set to "5" and all the fields you requested.
Why use variables instead of inline arguments?
Variables keep your operation reusable. You can change the values in the Variables panel without rewriting the mutation string itself.
This mirrors how real client applications send mutations. The operation stays constant and only the variable payload changes per request.
- Now confirm the new game persists by running the games query. Open a new tab in the Operation panel (click the + button) and paste:
query {
games {
id
title
platform
}
}
- Click the play button to run this query.
- You should see 5 games in the response, including the Hollow Knight: Silksong entry you just added.
What about persistence?
The data lives in the games array in memory. New games persist as long as the server is running. If you stop the server and restart it, the array resets to the original four games.
New game not showing up in the query?
Make sure you ran the mutation first (check the Response panel for a successful result with an id field). If you restarted the server between the mutation and the query, the in-memory data resets.
Help me figure out why my mutation data disappeared.
Secret mission
Add Filtering and an Update Mutation
Your API can fetch all games and add new ones. But what if a user only wants to see their PC games? Or mark a game as completed without deleting and re-adding it? Level up your API with query filtering and an update mutation.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- The game-library-api project folder on your Desktop.
- The Apollo Server process running on port 4000.
- npm packages (@apollo/server and graphql) installed inside the project folder.
Keep everything running
No action needed. Choose this if you're still actively building or experimenting with your GraphQL API.
- Your server will keep running until you close the terminal or press Ctrl+C.
- You can restart it anytime by running npm start from inside the game-library-api folder.
Pause - I'll come back to this later
Stop the running server to free up the terminal, but keep your project files for later.
- In the terminal where your server is running, press Ctrl+C to stop the server.
- Your game-library-api folder stays on your Desktop. To resume, open the folder in VS Code and run npm start again.
Delete - I don't want to use this again
Remove all project files and stop the server completely.
- In the terminal where your server is running, press Ctrl+C to stop the server.
- Delete the project folder by running this command (macOS/Linux):
rm -rf ~/Desktop/game-library-api
On Windows, run this instead:
rmdir /s /q %USERPROFILE%\Desktop\game-library-api
- Confirm the folder is gone by running ls ~/Desktop (macOS/Linux) or dir %USERPROFILE%\Desktop (Windows). You should no longer see game-library-api in the output.
Nice Work!
Nice Work!
You just built a fully functional GraphQL API from scratch using Apollo Server 5 and Node.js. Your game library tracker can fetch data, add new entries, and respond to queries with exactly the fields a client requests.
You've learned how to:
- Defined a GraphQL schema using SDL with custom types, queries, and mutations that describe your API's capabilities.
- Built resolvers that handle data fetching and creation logic, connecting your schema to actual data.
- Tested queries and mutations interactively using Apollo Sandbox, seeing how GraphQL gives clients control over exactly what data they receive.
- Secret Mission: Added query filtering and an update mutation for more advanced data operations.
Ready to quiz yourself?