GraphQL Query Builder
Visually construct GraphQL queries — variables, nested fields, aliases, fragments, and directives
Operation
Variables
Declare $name: Type inputs passed at execution time. Check ! for required.
Fields
Type field names. Click args for arguments, @dir for directives, {} for nested sub-fields.
Fragments
Named fragments are spread automatically inside the operation body as ...FragmentName
You need a GraphQL query that fetches a user’s posts with comments, uses variables for the user ID, aliases two different posts calls (recent and popular), and includes a fragment for the shared author fields. Writing it by hand means matching braces across 4 nesting levels, remembering the $variable: Type! syntax, and hoping you didn’t forget a closing brace. One typo and the GraphQL playground gives you a cryptic syntax error.
Why This Builder (Not GraphiQL or Apollo Sandbox)
GraphiQL and Apollo Sandbox require a running GraphQL server with introspection enabled — great for existing APIs, useless when you’re drafting queries for a schema that’s still being designed, or writing documentation examples. This tool builds queries visually — add fields, nest objects, define variables, create fragments, set aliases, add directives — and outputs the complete GraphQL document. Everything runs in your browser; no server connection needed, no data sent anywhere.
What Is a GraphQL Query?
GraphQL is a query language for APIs that gives clients precise control over the data they receive. Unlike REST endpoints that return fixed response shapes, a GraphQL query is a selection set — you specify exactly which fields you want, at any nesting depth, and the server returns only that data.
A GraphQL document can contain three operation types:
- query — read-only data fetching (most common)
- mutation — write operations (create, update, delete)
- subscription — real-time event streams over WebSocket
Anatomy of a GraphQL Query
query GetUser($userId: ID!, $showEmail: Boolean = true) {
user(id: $userId) {
id
name
email @include(if: $showEmail)
posts {
title
publishedAt
}
}
...UserMeta
}
fragment UserMeta on User {
createdAt
role
}
This example demonstrates all the core building blocks:
| Element | Example | Purpose |
|---|---|---|
| Operation type | query | Declares intent (read) |
| Operation name | GetUser | Identifies this operation for logging/caching |
| Variable definition | $userId: ID! | Declares a required input variable |
| Field selection | id, name | Chooses which fields to return |
| Field argument | user(id: $userId) | Passes a value into a field resolver |
| Directive | @include(if: $showEmail) | Conditionally includes a field |
| Nested selection | posts { title } | Traverses object relationships |
| Fragment spread | ...UserMeta | Reuses a named set of fields |
Variables: Keeping Queries Reusable
Hard-coding values directly in a query makes it impossible to reuse. GraphQL variables solve this:
# Bad: hard-coded
query { user(id: "123") { name } }
# Good: parameterized
query GetUser($userId: ID!) {
user(id: $userId) { name }
}
Variables are declared in the operation signature with a $ prefix and their type. The ! suffix marks a variable as required. Variables without ! are optional and may have a default value.
Common GraphQL scalar types for variables:
| Type | Description |
|---|---|
String | UTF-8 text |
Int | 32-bit integer |
Float | Double-precision float |
Boolean | true or false |
ID | Unique identifier (serialized as String) |
Custom scalar types (like DateTime, JSON, Upload) depend on the schema.
Fragments: Reusable Field Sets
Fragments let you define a named selection set once and spread it across multiple queries:
fragment UserCard on User {
id
name
avatarUrl
email
}
query GetUser($id: ID!) {
user(id: $id) {
...UserCard
posts { title }
}
}
query GetTeam($teamId: ID!) {
team(id: $teamId) {
members {
...UserCard
}
}
}
Fragments are especially useful in component-driven UIs (React, Vue) where each component declares its own data requirements as a fragment, and parent components compose them.
Aliases: Requesting the Same Field Twice
Aliases rename a field in the response. This is useful when you need the same field with different arguments in one query:
query ComparePrices {
usdPrice: product(currency: "USD") { price }
eurPrice: product(currency: "EUR") { price }
}
Without aliases, both selections would collide on product in the response.
Directives: Conditional Fields
GraphQL has two built-in directives for conditional field inclusion:
@include(if: $bool)— include the field only when$boolistrue@skip(if: $bool)— skip the field when$boolistrue
query GetProfile($showPrivate: Boolean!) {
user {
name
email @include(if: $showPrivate)
phone @skip(if: $showPrivate)
}
}
This avoids writing separate queries for different views of the same data.
Nested Fields and Object Relationships
GraphQL traverses object relationships through nested selection sets. Each nested { } block selects fields from the type returned by the parent field:
query {
organization { # returns Organization
name
teams { # returns [Team]
name
members { # returns [User]
id
name
role
}
}
}
}
The depth of nesting is unlimited in the query syntax, though servers typically enforce a maximum depth limit (often 10–15 levels) to prevent denial-of-service attacks.
Field Arguments
Arguments customize what a field resolver returns. Any field can accept arguments:
query {
users(limit: 10, offset: 20, orderBy: CREATED_AT_DESC) {
id
name
}
}
Argument values can be:
- Literal values:
"string",42,true,null - Enum values:
CREATED_AT_DESC(no quotes) - Variables:
$limit,$userId - Input objects:
{ field: value }(for complex filter inputs)
Mutations: Writing Data
Mutations follow the same syntax as queries but use the mutation keyword:
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
slug
author {
name
}
}
}
The selection set on a mutation specifies what the server should return after the write operation — this allows the client to update its cache in one round-trip.
Subscriptions: Real-Time Data
Subscriptions maintain a persistent connection (typically WebSocket) and push updates:
subscription OnMessageAdded($channelId: ID!) {
messageAdded(channelId: $channelId) {
id
text
sender {
name
avatarUrl
}
}
}
GraphQL vs REST: When to Use Each
| Criterion | GraphQL | REST |
|---|---|---|
| Data shape | Client-defined | Server-defined |
| Over-fetching | Eliminated | Common |
| Under-fetching | Eliminated (one query) | Often requires multiple requests |
| Caching | Complex (requires @cache hints or persisted queries) | Simple (HTTP caching) |
| File uploads | Requires multipart spec | Native support |
| Schema | Strongly typed | Optional (OpenAPI) |
| Tooling | Apollo, urql, URQL | Fetch, Axios, SWR |
GraphQL excels in: complex data graphs, mobile apps (bandwidth-sensitive), component-driven UIs, and API aggregation. REST excels in: simple CRUD resources, file transfers, and scenarios where HTTP caching is critical.
How to Use This Tool
- Select operation type — choose
query,mutation, orsubscription - Name the operation — optional but recommended for debugging and Apollo DevTools
- Add variables — declare
$name: Typepairs; check “Required” for mandatory inputs - Add fields — type field names; click args to add arguments, @dir for directives, {} to nest sub-fields
- Add fragments — name, type condition (
on TypeName), and fields; the tool spreads them automatically - Copy the generated query and variables JSON into your GraphQL client (Apollo Studio, GraphiQL, Insomnia, etc.)