About graphql-codegen
A GraphQL Code Generator reference skill for TypeScript developers, covering configuration, type generation, and client integrations. It is intended for projects generating type-safe code from GraphQL schemas and operation documents.
Key features
- 01CLI setup and code generation
- 02Client preset and type generation
- 03TanStack Query integration
- 04Fragment colocation
- 05Multiple schema configuration
- 06CI and watch mode
Use cases
- 01Generate TypeScript code from schemas and operation documents
- 02Generate client query hooks for GraphQL operations
- 03Watch documents and regenerate during development
MCP support
It mentions `mcp__documentation__fetch_docs` for retrieving in-depth graphql-codegen documentation.
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill graphql-codegenAfter installing, type/graphql-codegenin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
quick-ref/client-preset.mdreact-query.mdtyped-document-node.mdDetails
From the project READMEGraphQL Code Generator Core Knowledge
Deep Knowledge: Use
mcp__documentation__fetch_docswith technology:graphql-codegenfor 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: '[email protected]' },
});
};
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-codegenskill) - tRPC type-safe APIs (use
trpcskill) - GraphQL schema design (use
graphqlskill) - Non-TypeScript projects
- Simple GraphQL queries without type generation needs
Anti-Patterns
| Anti-Pattern | Why It's Bad | Solution |
|---|---|---|
| Committing generated files to git | Merge conflicts, outdated types | Add to .gitignore, generate in CI |
| Not using client preset | Verbose configuration | Use client preset for modern setup |
| Ignoring schema changes | Type mismatches at runtime | Run codegen in watch mode during dev |
| Missing operationId or query names | Poor generated hook names | Name all queries/mutations |
| Not using fragments | Code duplication | Use fragments for reusable fields |
| Generating types only | Missing runtime validation | Combine with schema validation |
| Hardcoding schema URL | Environment coupling | Use env variables for schema source |
| Not versioning generator packages | Inconsistent output across team | Pin generator versions |
Quick Troubleshooting
| Issue | Possible Cause | Solution |
|---|---|---|
| Generation fails | Invalid schema or documents | Validate schema, check GraphQL syntax |
| Type errors after generation | Schema/code mismatch | Regenerate types, check schema changes |
| Missing types | Documents path not matching files | Check documents glob pattern |
| Duplicate operation names | Same query name in multiple files | Use unique operation names |
| Fragment not found | Fragment not in documents | Include fragment file in documents |
| Hook not generated | Not using React Query plugin | Add typescript-react-query plugin |
| "Cannot find module './gql'" | Generation didn't run | Run npm run codegen |
| Slow generation | Too many documents | Optimize glob patterns, use ignoreNoDocuments |
| Type inference not working | Wrong import path | Import from generated gql folder |
Reference Documentation
Comments
Markdown supported