Strapi GraphQL Setup — Install Plugin, Schema Generation, Queries and Mutations
In this tutorial, you will install Strapi's Graphql plugin, explore the auto-generated GraphQL schema, and write queries and mutations to fetch and manipulate your content with the flexibility that GraphQL provides over REST.
What You'll Learn
- How to install the GraphQL plugin via command line and admin panel
- How GraphQL schema is auto-generated from your content types
- How to write queries with filtering, sorting, and population
- How to write mutations for creating, updating, and deleting content
- How to use the GraphQL playground for testing
- GraphQL-specific features like fragments and aliases
Why It Matters
GraphQL gives frontend teams complete control over what data they fetch. Instead of the REST approach where the server decides the response shape, GraphQL lets the client request exactly what it needs. This eliminates over-fetching (too much data) and under-fetching (too little data), making frontends faster and more maintainable.
Real-World Use
A product listing page needs product name, price, and thumbnail. The product detail page needs name, price, description, images, reviews, and related products. With REST, you would need two endpoints or accept that the list endpoint returns too much data. With GraphQL, the same endpoint handles both — the frontend requests only what it needs for each page.
Learning Path
flowchart LR A["REST API"] --> B["API Parameters"] B --> C["GraphQL Setup
-- You are here"]:::current C --> D["API Customization"] D --> E["API Security"] classDef current fill:#4945ff,color:#fff,stroke-width:2px
Installing the GraphQL Plugin
The GraphQL plugin is separate from Strapi core. You install it like any other plugin.
# Install using the Strapi CLI
npm run strapi install graphql
# Or install via npm directly
npm install @strapi/plugin-graphql
# After installation, rebuild the admin panel
npm run build
After installation, the GraphQL endpoint is available at http://localhost:1337/graphql. Strapi also adds a GraphQL playground (if enabled in development) where you can test queries.
To verify the installation:
# Test the GraphQL endpoint
curl -X POST http://localhost:1337/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ __schema { types { name } } }"}'
The response includes the complete GraphQL schema with all your content types reflected as queryable types.
Auto-Generated Schema
Strapi automatically generates a GraphQL schema from your content types. Every collection type and single type becomes a GraphQL type.
For a content type "Article" with fields title, content, and author, Strapi generates:
type Article {
id: ID!
title: String
content: String
author: Author
createdAt: DateTime
updatedAt: DateTime
publishedAt: DateTime
}
type ArticleEntity {
id: ID!
attributes: Article!
}
type ArticleEntityResponse {
data: ArticleEntity
}
type ArticleEntityResponseCollection {
data: [ArticleEntity!]!
meta: ResponseMeta!
}
The naming convention follows: {ContentType}, {ContentType}Entity, {ContentType}EntityResponse, and {ContentType}EntityResponseCollection.
Writing Queries
GraphQL queries fetch data. Here is how the REST equivalents translate to GraphQL:
# Equivalent to GET /api/articles
query {
articles {
data {
id
attributes {
title
content
createdAt
}
}
meta {
pagination {
total
page
pageSize
}
}
}
}
# Equivalent to GET /api/articles/1
query {
article(id: 1) {
data {
id
attributes {
title
content
}
}
}
}
The id field is at the same level as attributes, not inside it. This mirrors the REST API response structure.
Filtering and Sorting in GraphQL
GraphQL uses named arguments for filtering and sorting:
# Filtering with operators
query {
articles(
filters: {
title: { containsi: "strapi" }
createdAt: { gte: "2026-01-01" }
}
) {
data {
id
attributes { title }
}
}
}
# Sorting
query {
articles(sort: ["createdAt:desc", "title:asc"]) {
data {
id
attributes { title createdAt }
}
}
}
# Pagination
query {
articles(pagination: { page: 1, pageSize: 10 }) {
data {
id
attributes { title }
}
meta {
pagination {
total
pageCount
}
}
}
}
GraphQL operators follow the same names as REST but in camelCase: containsi, eq, ne, gt, gte, lt, lte, in, notIn, null, notNull.
Populating Relations in GraphQL
In GraphQL, you access relations by adding their fields to the query:
# Populate author relation
query {
articles {
data {
id
attributes {
title
author {
data {
id
attributes {
name
email
}
}
}
}
}
}
}
# Deeply nested population
query {
articles {
data {
attributes {
title
author {
data {
attributes {
name
articles {
data {
attributes { title }
}
}
}
}
}
}
}
}
}
GraphQL population is natural — you just query the fields you want. The nesting is unlimited (within practical performance limits).
Writing Mutations
Mutations create, update, and delete data:
# Create an article
mutation {
createArticle(data: {
title: "New Article"
content: "Content here"
author: 1
}) {
data {
id
attributes {
title
createdAt
}
}
}
}
# Update an article
mutation {
updateArticle(
id: 1
data: {
title: "Updated Title"
}
) {
data {
id
attributes { title }
}
}
}
# Delete an article
mutation {
deleteArticle(id: 3) {
data {
id
attributes { title }
}
}
}
The mutation names follow the pattern create{ContentType}, update{ContentType}, and delete{ContentType}.
Using the GraphQL Playground
When the plugin is installed, you can access the GraphQL playground at http://localhost:1337/graphql. The playground provides:
- A query editor with syntax highlighting
- Schema documentation browser
- Query history
- Response viewer
The playground is enabled in development mode by default. In production, disable it by setting apolloServer.introspection to false in the plugin configuration.
// config/plugins.js
module.exports = {
graphql: {
config: {
endpoint: "/graphql",
shadowCRUD: true,
apolloServer: {
introspection: process.env.NODE_ENV === "development",
},
},
},
};
GraphQL Fragments
Fragments let you reuse field selections across multiple queries:
# Define a fragment
fragment ArticleFields on Article {
title
content
createdAt
author {
data {
attributes {
name
}
}
}
}
# Use the fragment
query {
articles {
data {
id
attributes {
...ArticleFields
}
}
}
}
fragment ArticleFields on Article {
title
content
createdAt
author {
data {
attributes {
name
}
}
}
}
Fragments keep your queries DRY. When you need to adjust the fields, you change the fragment once instead of every query.
Common Mistakes
Requesting all fields without thinking. GraphQL makes it easy to request every available field. This can create massive responses. Only request the fields your component actually renders.
Nesting queries too deeply. GraphQL queries with 5+ levels of nested relations generate many database queries. Monitor performance and limit nesting depth.
Forgetting the data wrapper nesting. The response structure is
data -> idanddata -> attributes -> fields. Newcomers often look for fields directly on the data level.Not using query variables. Hardcoding values in queries makes them inflexible and unsafe. Use variables for dynamic values like IDs and filter inputs.
Leaving the playground enabled in production. The playground exposes your full schema to anyone who visits the endpoint. Disable introspection in production for security.
Practice Questions
Write a GraphQL query that fetches the title and author name of the 5 most recent articles. Answer:
query { articles(sort: ["createdAt:desc"], pagination: { pageSize: 5 }) { data { id attributes { title author { data { attributes { name } } } } } } }How do you create a new article with a relation to an existing author using GraphQL? Answer: Use the
createArticlemutation with the author ID:mutation { createArticle(data: { title: "...", content: "...", author: 1 }) { data { id } } }What is the benefit of using fragments in GraphQL? Answer: Fragments let you define a set of fields once and reuse them across multiple queries. Changes to the fragment automatically apply to all queries that use it, keeping queries DRY.
Challenge: Build a complete GraphQL API client for a React frontend. Create components that (1) List articles with title, author, and published date, (2) Show a single article with all fields and nested relations, (3) Provide a form to create new articles, (4) Implement search with GraphQL filters. Use Apollo Client or a simple fetch-based GraphQL client.
FAQ
Mini Project
Your task: Convert a REST API integration to GraphQL.
- Install the GraphQL plugin in your Strapi project.
- Using the GraphQL playground, write and test queries that:
- Fetch all articles with author, tags, and category populated
- Fetch a single article by ID with all nested relations three levels deep
- Create a new article with relations
- Update the category of an existing article
- Delete a tag that is no longer needed
- Compare the response structure between REST and GraphQL for the same data.
- Create a simple HTML page that uses fetch to call the GraphQL endpoint and renders the results.
What's Next
Now that you have GraphQL set up, proceed to API Customization to learn how to add custom controllers, routes, services, and middlewares to extend Strapi's default API behavior. After that, secure your API with API Security.
Related lessons:
- GraphQL Basics — Understanding GraphQL fundamentals
- REST API — Comparing REST and GraphQL
- Node.js — How Strapi processes GraphQL
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro