Set up GraphQL codegen

Generate TypeScript types from your Fontdue GraphQL queries so data flows typed from the query into your components.

GraphQL codegen reads your .graphql query files, checks them against your schema, and writes a TypeScript type for each one. Pass that type to a fetch and the whole result is typed – data.viewer.fontCollections and everything under it – with an editor flagging any field the query didn’t ask for. The example template ships with this already configured, so cloning it gets you typed queries with nothing to set up. This page is for adding the same toolchain to a project of your own, or understanding how the template’s is wired.

It builds on the fetchGraphql helper, which is generic over the query and variables types: fetchGraphql<IndexQuery, IndexQueryVariables>(...). Codegen is what produces those IndexQuery and IndexQueryVariables types.

Install the tooling

Add the codegen CLI and the two plugins that emit operation types, plus dotenv so the config can read your endpoint from .env.local:

npm install --save-dev graphql @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations dotenv

Configure it

Point codegen at your schema (the live endpoint) and your query files. The config below writes a single operations-types.ts with one type per operation:

# codegen.yml
schema: ${NEXT_PUBLIC_FONTDUE_URL}/graphql
documents: "./src/queries/*.graphql"
generates:
operations-types.ts:
config:
onlyOperationTypes: true
preResolveTypes: true
skipTypename: true
avoidOptionals: true
plugins:
- typescript
- typescript-operations

onlyOperationTypes keeps the output to the types your queries actually use rather than the entire schema; preResolveTypes inlines them into readable shapes instead of deep generic wrappers; skipTypename drops the __typename fields you didn’t ask for; and avoidOptionals emits T | null rather than optional T?, which matches how the API returns absent fields.11avoidOptionals is why query results are dotted through with ?. and ! in the example – nullable fields are null, not missing, so you null-check rather than treat them as optional.

Run it in watch mode

Reading the schema from the live endpoint means codegen needs NEXT_PUBLIC_FONTDUE_URL at run time. Load it from .env.local with dotenv, and run codegen alongside the Next.js dev server so types regenerate as you edit queries:

"scripts": {
"dev": "run-p next-dev codegen",
"next-dev": "next dev",
"codegen": "DOTENV_CONFIG_PATH=.env.local graphql-codegen -r dotenv/config --watch"
}

run-p runs both processes together22run-p is from npm-run-allnpm install --save-dev npm-run-all if it isn’t already a dependency., so a single npm run dev starts the server and the watcher. Each save to a file in src/queries/ rewrites operations-types.ts with one type per query – IndexQuery, FontQuery, FontQueryVariables, and so on.

Reference the generated types

The output file is easiest to import through a path alias. The template aliases @graphql to the generated file (and @/* to src/*) in tsconfig.json:

{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@graphql": ["./operations-types.ts"]
}
}
}

With that in place, import the type next to the fetch and hand it to the helper:

import { fetchGraphql } from "@/lib/graphql";
import { IndexQuery } from "@graphql";
const data = await fetchGraphql<IndexQuery>("Index.graphql");

From here the typed data flows into your pages exactly as it does in the walkthrough – see Query the GraphQL API for the fetch helper and Build font pages for a query and its fragment driving a whole detail page.

1 avoidOptionals is why query results are dotted through with ?. and ! in the example – nullable fields are null, not missing, so you null-check rather than treat them as optional. 
2 run-p is from npm-run-allnpm install --save-dev npm-run-all if it isn’t already a dependency.