---
name: graphql-api-builder
description: "Design GraphQL schemas, resolvers, and subscriptions with Apollo Server or Pothos. Designs type-safe GraphQL APIs — schemas, resolvers, N+1-safe DataLoader batching, subscriptions, and Apollo Federation. Supports Apollo Server 4, Pothos schema-builder, and Nexus code-first patterns."
license: MIT
---

# GraphQL API Builder

Scaffolds production-shaped GraphQL APIs in TypeScript: typed schemas, resolvers wired to DataLoader, real-time subscriptions, and federated subgraphs. It's aimed at backend and fullstack engineers who already know GraphQL conceptually but don't want to hand-write boilerplate or rediscover the N+1 trap on every new field. The skill targets three concrete stacks — Apollo Server 4, Pothos (code-first schema-builder), and Nexus — and matches the conventions of whichever it detects in your repo.

## When to use it

- Starting a new GraphQL service and choosing between SDL-first and code-first.
- Adding a resolver that fetches related entities (author → posts → comments) and you want batching from the start.
- Standing up `graphql-ws` subscriptions and the `PubSub` plumbing behind them.
- Splitting a monolithic schema into Apollo Federation subgraphs with `@key` and reference resolvers.
- Porting an Apollo SDL schema to Pothos builder calls, or vice versa.

## How it works

For **Pothos**, it generates `builder.objectRef`, `builder.queryType`, and `t.field` definitions with the plugins you'd actually want — `@pothos/plugin-dataloader`, `relay`, and `prisma` — and respects your `SchemaTypes` generics. For **Apollo Server 4**, it produces `typeDefs`, `resolvers`, and a `startStandaloneServer` (or `expressMiddleware`) bootstrap. DataLoader is wired per-request in the context factory so caches don't leak between requests. Subscriptions use `graphql-subscriptions` `PubSub` (or a Redis-backed `PubSub` when you ask) plus a `graphql-ws` `useServer` setup on a separate WS path.

## Example

```ts
// Pothos: a batched, N+1-safe relation
const User = builder.loadableObject('User', {
  load: (ids: string[]) => db.user.findMany({ where: { id: { in: ids } } }),
  fields: (t) => ({
    id: t.exposeID('id'),
    posts: t.field({
      type: [Post],
      resolve: (user, _args, ctx) => ctx.loaders.postsByUser.load(user.id),
    }),
  }),
});
```

## Tips & gotchas

- **Build a fresh DataLoader per request.** A loader created at module scope caches across users and serves stale or leaked data. The skill always instantiates loaders inside the context function.
- **`graphql-ws` ≠ `subscriptions-transport-ws`.** The latter is deprecated; generated clients and the server both use `graphql-ws`. Don't mix protocols.
- **Federation needs the right build.** Apollo Federation subgraphs use `buildSubgraphSchema` from `@apollo/subgraph`, not the plain `makeExecutableSchema` — reference resolvers (`__resolveReference`) are generated alongside each `@key` type.
- In Pothos, prefer `loadableObject`/`loadableGroup` over a manual loader map when the batching key is the object's own id.

## FAQ

**Code-first or SDL-first?** Pothos/Nexus (code-first) give end-to-end type inference with no codegen step; Apollo SDL is more portable and tooling-friendly. The skill supports both and will follow your existing choice.

**Does it handle the N+1 problem automatically?** It generates DataLoader-backed resolvers for relations by default, but you still decide the batch key. It flags resolvers that fetch per-parent without a loader.

**Can I add it to an existing Apollo server?** Yes — it detects your `resolvers` and `typeDefs` structure and emits additions that match, rather than scaffolding a new server.
