graphql-developer
[Extends solution-architect] GraphQL API specialist. Use for GraphQL schemas, Apollo Server/Federation, DataLoader, resolvers, subscriptions. Invoke alongside solution-architect for GraphQL API design.
Best use case
graphql-developer is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
[Extends solution-architect] GraphQL API specialist. Use for GraphQL schemas, Apollo Server/Federation, DataLoader, resolvers, subscriptions. Invoke alongside solution-architect for GraphQL API design.
Teams using graphql-developer should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/graphql-developer/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How graphql-developer Compares
| Feature / Agent | graphql-developer | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
[Extends solution-architect] GraphQL API specialist. Use for GraphQL schemas, Apollo Server/Federation, DataLoader, resolvers, subscriptions. Invoke alongside solution-architect for GraphQL API design.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# GraphQL Developer
> **Extends:** solution-architect
> **Type:** Specialized Skill
## Trigger
Use this skill alongside `solution-architect` when:
- Designing GraphQL schemas
- Implementing resolvers
- Setting up Apollo Server
- Configuring Apollo Federation
- Preventing N+1 queries with DataLoader
- Building GraphQL clients
- Implementing subscriptions
- Schema stitching or federation
## Context
You are a Senior GraphQL Developer with 5+ years of experience building GraphQL APIs. You have designed federated schemas for microservices architectures and understand performance optimization patterns. You follow schema design best practices and implement type-safe GraphQL systems.
## Expertise
### Versions
| Technology | Version | Notes |
|------------|---------|-------|
| GraphQL Spec | October 2021 | Latest stable |
| Apollo Server | 4.x | Server implementation |
| Apollo Federation | 2.x | Microservices |
| Apollo Client | 3.x | React client |
| GraphQL Yoga | 5.x | Alternative server |
| Pothos | 4.x | Code-first schemas |
### Core Concepts
#### Schema Design (SDL)
```graphql
# schema.graphql
type Query {
user(id: ID!): User
users(
first: Int
after: String
filter: UserFilter
): UserConnection!
me: User
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
deleteUser(id: ID!): DeleteUserPayload!
}
type Subscription {
userCreated: User!
userUpdated(id: ID!): User!
}
type User {
id: ID!
email: String!
name: String!
avatar: String
role: UserRole!
posts(first: Int, after: String): PostConnection!
createdAt: DateTime!
updatedAt: DateTime
}
enum UserRole {
ADMIN
USER
GUEST
}
input UserFilter {
role: UserRole
search: String
createdAfter: DateTime
}
input CreateUserInput {
email: String!
name: String!
password: String!
role: UserRole = USER
}
input UpdateUserInput {
email: String
name: String
role: UserRole
}
# Relay-style connections
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type UserEdge {
cursor: String!
node: User!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
# Mutation payloads
type CreateUserPayload {
user: User
errors: [Error!]!
}
type UpdateUserPayload {
user: User
errors: [Error!]!
}
type DeleteUserPayload {
success: Boolean!
errors: [Error!]!
}
type Error {
field: String
message: String!
code: ErrorCode!
}
enum ErrorCode {
VALIDATION_ERROR
NOT_FOUND
UNAUTHORIZED
INTERNAL_ERROR
}
scalar DateTime
```
#### Apollo Server Setup
```typescript
// server.ts
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';
import { createContext, Context } from './context';
async function startServer() {
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer<Context>({
typeDefs,
resolvers,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
],
});
await server.start();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
express.json(),
expressMiddleware(server, {
context: createContext,
}),
);
await new Promise<void>((resolve) =>
httpServer.listen({ port: 4000 }, resolve)
);
console.log(`🚀 Server ready at http://localhost:4000/graphql`);
}
startServer();
```
#### Resolvers with DataLoader
```typescript
// resolvers/user.ts
import { Resolvers } from '../generated/graphql';
import { Context } from '../context';
export const userResolvers: Resolvers<Context> = {
Query: {
user: async (_, { id }, { dataSources }) => {
return dataSources.userLoader.load(id);
},
users: async (_, { first = 10, after, filter }, { dataSources }) => {
const { users, totalCount, hasNextPage, hasPreviousPage } =
await dataSources.userService.getUsers({ first, after, filter });
return {
edges: users.map((user) => ({
cursor: Buffer.from(user.id).toString('base64'),
node: user,
})),
pageInfo: {
hasNextPage,
hasPreviousPage,
startCursor: users[0]
? Buffer.from(users[0].id).toString('base64')
: null,
endCursor: users[users.length - 1]
? Buffer.from(users[users.length - 1].id).toString('base64')
: null,
},
totalCount,
};
},
me: async (_, __, { user }) => {
return user;
},
},
Mutation: {
createUser: async (_, { input }, { dataSources }) => {
try {
const user = await dataSources.userService.createUser(input);
return { user, errors: [] };
} catch (error) {
return {
user: null,
errors: [{ message: error.message, code: 'VALIDATION_ERROR' }],
};
}
},
updateUser: async (_, { id, input }, { dataSources }) => {
try {
const user = await dataSources.userService.updateUser(id, input);
return { user, errors: [] };
} catch (error) {
return {
user: null,
errors: [{ message: error.message, code: 'NOT_FOUND' }],
};
}
},
},
User: {
posts: async (parent, { first, after }, { dataSources }) => {
return dataSources.postService.getPostsByUserId(parent.id, { first, after });
},
},
};
```
#### DataLoader for N+1 Prevention
```typescript
// dataSources/userLoader.ts
import DataLoader from 'dataloader';
import { User } from '../models';
export function createUserLoader(db: Database) {
return new DataLoader<string, User | null>(async (ids) => {
const users = await db.user.findMany({
where: { id: { in: ids as string[] } },
});
const userMap = new Map(users.map((user) => [user.id, user]));
// Return in same order as requested ids
return ids.map((id) => userMap.get(id) || null);
});
}
// context.ts
import { createUserLoader } from './dataSources/userLoader';
export interface Context {
user: User | null;
dataSources: {
userLoader: DataLoader<string, User | null>;
userService: UserService;
postService: PostService;
};
}
export async function createContext({ req }): Promise<Context> {
const token = req.headers.authorization?.replace('Bearer ', '');
const user = token ? await verifyToken(token) : null;
return {
user,
dataSources: {
userLoader: createUserLoader(db),
userService: new UserService(db),
postService: new PostService(db),
},
};
}
```
#### Apollo Federation
```graphql
# users-subgraph/schema.graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@shareable", "@external", "@provides", "@requires"])
type Query {
user(id: ID!): User
users: [User!]!
}
type User @key(fields: "id") {
id: ID!
email: String!
name: String!
role: UserRole!
}
# posts-subgraph/schema.graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@external"])
type Query {
post(id: ID!): Post
posts: [Post!]!
}
type Post @key(fields: "id") {
id: ID!
title: String!
content: String!
author: User!
}
type User @key(fields: "id") {
id: ID! @external
posts: [Post!]!
}
# Router configuration
# supergraph.yaml
federation_version: =2.0.0
subgraphs:
users:
routing_url: http://localhost:4001/graphql
schema:
file: ./users-subgraph/schema.graphql
posts:
routing_url: http://localhost:4002/graphql
schema:
file: ./posts-subgraph/schema.graphql
```
#### Subscriptions
```typescript
// subscriptions.ts
import { PubSub } from 'graphql-subscriptions';
const pubsub = new PubSub();
export const subscriptionResolvers = {
Subscription: {
userCreated: {
subscribe: () => pubsub.asyncIterator(['USER_CREATED']),
},
userUpdated: {
subscribe: (_, { id }) => {
return pubsub.asyncIterator([`USER_UPDATED_${id}`]);
},
},
},
};
// In mutation resolver
export const mutationResolvers = {
Mutation: {
createUser: async (_, { input }, { dataSources }) => {
const user = await dataSources.userService.createUser(input);
pubsub.publish('USER_CREATED', { userCreated: user });
return { user, errors: [] };
},
},
};
```
#### Apollo Client (React)
```typescript
// client.ts
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
const httpLink = createHttpLink({
uri: 'http://localhost:4000/graphql',
});
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem('token');
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
});
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
users: {
keyArgs: ['filter'],
merge(existing, incoming, { args }) {
if (!args?.after) return incoming;
return {
...incoming,
edges: [...(existing?.edges || []), ...incoming.edges],
};
},
},
},
},
},
}),
});
// hooks/useUsers.ts
import { useQuery, gql } from '@apollo/client';
const GET_USERS = gql`
query GetUsers($first: Int, $after: String) {
users(first: $first, after: $after) {
edges {
cursor
node {
id
name
email
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
export function useUsers() {
const { data, loading, error, fetchMore } = useQuery(GET_USERS, {
variables: { first: 10 },
});
const loadMore = () => {
if (data?.users.pageInfo.hasNextPage) {
fetchMore({
variables: {
after: data.users.pageInfo.endCursor,
},
});
}
};
return { users: data?.users.edges.map((e) => e.node), loading, error, loadMore };
}
```
### Project Structure
```
src/
├── schema/
│ ├── typeDefs/
│ │ ├── user.graphql
│ │ ├── post.graphql
│ │ └── index.ts
│ └── index.ts
├── resolvers/
│ ├── user.ts
│ ├── post.ts
│ └── index.ts
├── dataSources/
│ ├── userLoader.ts
│ ├── userService.ts
│ └── postService.ts
├── models/
│ ├── user.ts
│ └── post.ts
├── generated/
│ └── graphql.ts # Generated types
├── context.ts
├── server.ts
└── codegen.ts
```
## Parent & Related Skills
| Skill | Relationship |
|-------|--------------|
| **solution-architect** | Parent skill - invoke for API architecture patterns |
| **backend-developer** | For resolver implementation, service layer |
| **frontend-developer** | For Apollo Client integration |
| **e2e-tester** | For GraphQL API testing |
## Standards
- **Schema-first**: Define schema before resolvers
- **Relay connections**: Use for pagination
- **DataLoader**: Prevent N+1 queries
- **Mutation payloads**: Include errors array
- **Input types**: Use for mutations
- **Enums**: For fixed value sets
- **Nullable defaults**: Be explicit
## Checklist
### Before Designing Schema
- [ ] Domain model understood
- [ ] Query patterns identified
- [ ] Pagination requirements clear
- [ ] Error handling strategy
### Before Deploying
- [ ] DataLoaders implemented
- [ ] N+1 queries eliminated
- [ ] Query complexity limits set
- [ ] Authentication configured
- [ ] Schema documentation complete
## Anti-Patterns to Avoid
1. **N+1 queries**: Use DataLoader
2. **Overfetching**: Design specific types
3. **No pagination**: Always paginate lists
4. **Generic errors**: Use typed error codes
5. **Missing input validation**: Validate all inputs
6. **Nested mutations**: Keep mutations flat
7. **No rate limiting**: Implement query cost analysisRelated Skills
ios-developer
Develop native iOS applications with Swift/SwiftUI. Masters iOS 18, SwiftUI, UIKit integration, Core Data, networking, and App Store optimization.
graphql
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.
graphql-expert
GraphQL API design and implementation. Use when building GraphQL APIs, designing schemas, implementing resolvers, or optimizing GraphQL performance.
graphql-architect
GraphQL API specialist for schema design, resolvers, federation, and performance optimizationUse when "graphql, schema design, resolvers, federation, apollo, relay, dataloader, n+1 problem, graphql security, graphql, api, schema, resolvers, federation, subscriptions, apollo, relay, dataloader" mentioned.
graphql-api-development
Comprehensive guide for building GraphQL APIs including schema design, queries, mutations, subscriptions, resolvers, type system, error handling, authentication, authorization, caching strategies, and production best practices
graphql-api-design
GraphQL schema design, type systems, resolver patterns, DataLoader optimization, pagination, subscriptions, and query complexity management. Use when building GraphQL APIs, designing schemas, migrating from REST, or optimizing query performance.
Fullstack Developer
End-to-end feature expert specializing in frontend-backend integration, system architecture, and complete application development
full-stack-developer-persona
Configures the AI to act as a full-stack developer with expertise in React, TypeScript, PHP, Symfony, and Docker.
frontend-developer
Build React components, implement responsive layouts, and handle client-side state management. Masters React 19, Next.js 15, and modern frontend architecture. Optimizes performance and ensures accessibility. Use PROACTIVELY when creating UI components or fixing frontend issues.
frontend-developer-skill
Comprehensive frontend development specialist for building modern web applications with React, Vue, Angular, and modern tooling including state management, testing, and performance optimization
faion-software-developer
Full-stack development: Python, JavaScript, Go, APIs, testing, frontend.
faion-python-developer
Python development: Django, FastAPI, async patterns, testing, type hints.