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.

16 stars

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

$curl -o ~/.claude/skills/graphql-developer/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/graphql-developer/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/graphql-developer/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How graphql-developer Compares

Feature / Agentgraphql-developerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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 analysis

Related Skills

ios-developer

16
from diegosouzapw/awesome-omni-skill

Develop native iOS applications with Swift/SwiftUI. Masters iOS 18, SwiftUI, UIKit integration, Core Data, networking, and App Store optimization.

graphql

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

GraphQL API design and implementation. Use when building GraphQL APIs, designing schemas, implementing resolvers, or optimizing GraphQL performance.

graphql-architect

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-skill

End-to-end feature expert specializing in frontend-backend integration, system architecture, and complete application development

full-stack-developer-persona

16
from diegosouzapw/awesome-omni-skill

Configures the AI to act as a full-stack developer with expertise in React, TypeScript, PHP, Symfony, and Docker.

frontend-developer

16
from diegosouzapw/awesome-omni-skill

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

16
from diegosouzapw/awesome-omni-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

16
from diegosouzapw/awesome-omni-skill

Full-stack development: Python, JavaScript, Go, APIs, testing, frontend.

faion-python-developer

16
from diegosouzapw/awesome-omni-skill

Python development: Django, FastAPI, async patterns, testing, type hints.