GraphQL Code Generator Core Knowledge

SkillDocs & knowledge

GraphQL Code Generator for TypeScript. Generates typed operations, hooks, and document nodes from GraphQL schemas. Use for type-safe GraphQL in frontend.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the GraphQL Code Generator Core Knowledge skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/api-integration/graphql-codegen/SKILL.md and read by ahel’s review.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: graphql-codegen for comprehensive documentation.

Installation

npm install -D @graphql-codegen/cli @graphql-codegen/typescript \
  @graphql-codegen/typescript-operations @graphql-codegen/client-preset

Basic Configuration

// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.tsx', 'src/**/*.ts'],
  ignoreNoDocuments: true,
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        documentMode: 'string',
      },
    },
  },
};

export default config;

Run Generation

npx graphql-codegen
npx graphql-codegen --watch  # Watch mode

Client Preset (Recommended)

The client preset generates everything needed for type-safe GraphQL.

// codegen.ts
const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.tsx'],
  generates: {
    './src/gql/': {
      preset: 'client',
      plugins: [],
      presetConfig: {
        gqlTagName: 'gql',
        fragmentMasking: { unmaskFunctionName: 'getFragmentData' },
      },
    },
  },
};

Usage

import { gql } from '../gql';
import { useQuery } from '@apollo/client';

const GET_USER = gql(`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`);

function UserProfile({ id }: { id: string }) {
  const { data, loading } = useQuery(GET_USER, {
    variables: { id },
  });

  if (loading) return <Spinner />;
  // data.user is fully typed
  return <div>{data?.user?.name}</div>;
}

TanStack Query Integration

npm install -D @graphql-codegen/typescript-react-query
// codegen.ts
const config: CodegenConfig = {
  schema: 'http://localhost:4000/graphql',
  documents: ['src/**/*.graphql'],
  generates: {
    './src/gql/index.ts': {
      plugins: [
        'typescript',
        'typescript-operations',
        'typescript-react-query',
      ],
      config: {
        fetcher: {
          func: './fetcher#fetcher',
          isReactHook: false,
        },
        reactQueryVersion: 5,
        addInfiniteQuery: true,
      },
    },
  },
};

Fetcher

// src/gql/fetcher.ts
export const fetcher = <TData, TVariables>(
  query: string,
  variables?: TVariables
): (() => Promise<TData>) => {
  return async () => {
    const response = await fetch('http://localhost:4000/graphql', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${getToken()}`,
      },
      body: JSON.stringify({ query, variables }),
    });

    const json = await response.json();
    if (json.errors) {
      throw new Error(json.errors[0].message);
    }
    return json.data;
  };
};

Generated Hooks Usage

import { useGetUserQuery, useCreateUserMutation } from './gql';

function UserProfile({ id }: { id: string }) {
  const { data, isLoading } = useGetUserQuery({ id });
  const createMutation = useCreateUserMutation();

  const handleCreate = () => {
    createMutation.mutate({
      input: { name: 'John', email: 'john@example.com' },
    });
  };

  if (isLoading) return <Spinner />;
  return <div>{data?.user?.name}</div>;
}

Fragment Colocation

// components/UserAvatar.tsx
import { gql, FragmentType, getFragmentData } from '../gql';

export const USER_AVATAR_FRAGMENT = gql(`
  fragment UserAvatar on User {
    id
    name
    avatarUrl
  }
`);

interface Props {
  user: FragmentType<typeof USER_AVATAR_FRAGMENT>;
}

export function UserAvatar({ user }: Props) {
  const data = getFragmentData(USER_AVATAR_FRAGMENT, user);
  return <img src={data.avatarUrl} alt={data.name} />;
}

// Usage in parent query
const GET_USER = gql(`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      ...UserAvatar
    }
  }
`);

Production Readiness

Schema Polling

// codegen.ts
const config: CodegenConfig = {
  schema: [
    {
      'http://localhost:4000/graphql': {
        headers: {
          Authorization: `Bearer ${process.env.GRAPHQL_TOKEN}`,
        },
      },
    },
  ],
  // ...
};

Multiple Schemas

const config: CodegenConfig = {
  generates: {
    './src/gql/user-api/': {
      schema: 'http://user-api:4000/graphql',
      documents: ['src/features/user/**/*.tsx'],
      preset: 'client',
    },
    './src/gql/product-api/': {
      schema: 'http://product-api:4001/graphql',
      documents: ['src/features/product/**/*.tsx'],
      preset: 'client',
    },
  },
};

CI/CD Integration

# .github/workflows/codegen.yml
name: GraphQL Codegen

on:
  push:
    paths:
      - 'src/**/*.graphql'
      - 'src/**/*.tsx'

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npx graphql-codegen
      - name: Check for changes
        run: |
          if [[ -n $(git status --porcelain src/gql) ]]; then
            echo "Generated files changed"
            exit 1
          fi

Package Scripts

{
  "scripts": {
    "codegen": "graphql-codegen",
    "codegen:watch": "graphql-codegen --watch"
  }
}

Checklist

  • Schema source configured (URL or local)
  • Documents path matches source files
  • Client preset for optimal output
  • Fetcher configured with auth
  • Fragment colocation pattern
  • Watch mode for development
  • CI validation of generated code
  • TypeScript strict mode compatible

When NOT to Use This Skill

  • REST API type generation (use openapi-codegen skill)
  • tRPC type-safe APIs (use trpc skill)
  • GraphQL schema design (use graphql skill)
  • Non-TypeScript projects
  • Simple GraphQL queries without type generation needs

Anti-Patterns

Anti-PatternWhy It's BadSolution
Committing generated files to gitMerge conflicts, outdated typesAdd to .gitignore, generate in CI
Not using client presetVerbose configurationUse client preset for modern setup
Ignoring schema changesType mismatches at runtimeRun codegen in watch mode during dev
Missing operationId or query namesPoor generated hook namesName all queries/mutations
Not using fragmentsCode duplicationUse fragments for reusable fields
Generating types onlyMissing runtime validationCombine with schema validation
Hardcoding schema URLEnvironment couplingUse env variables for schema source
Not versioning generator packagesInconsistent output across teamPin generator versions

Quick Troubleshooting

IssuePossible CauseSolution
Generation failsInvalid schema or documentsValidate schema, check GraphQL syntax
Type errors after generationSchema/code mismatchRegenerate types, check schema changes
Missing typesDocuments path not matching filesCheck documents glob pattern
Duplicate operation namesSame query name in multiple filesUse unique operation names
Fragment not foundFragment not in documentsInclude fragment file in documents
Hook not generatedNot using React Query pluginAdd typescript-react-query plugin
"Cannot find module './gql'"Generation didn't runRun npm run codegen
Slow generationToo many documentsOptimize glob patterns, use ignoreNoDocuments
Type inference not workingWrong import pathImport from generated gql folder

Reference Documentation

Signals

GitHub stars
33
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
graphql-codegen
Source
github.com/claude-dev-suite/claude-dev-suite