| name | graphql-schema-design-style |
| description | Design and evolve GraphQL schemas (SDL/code-first): types, nullability, connections, mutations, errors, and versioning style. Use when GraphQL schema design, SDL review, GraphQL API modeling, Relay connections, input types, or schema evolution—not for offensive GraphQL recon alone.
|
GraphQL Schema Design Style
Standards for GraphQL schema shape and evolution: types, fields, arguments,
nullability, pagination, mutations, and error contracts. Prefer the repo’s
GraphQL stack and neighboring types. This is design, not live-endpoint recon.
Use When
- Authoring or reviewing GraphQL SDL, code-first schemas, or schema modules
- Modeling objects, interfaces, unions, enums, inputs, and custom scalars
- Choosing nullability, pagination (Relay vs offset), and mutation payloads
- Evolving a public GraphQL API without silent breaks; aligning resolvers/codegen
- Triggers: GraphQL schema design, SDL, connections, mutation design, nullability
Do not use as primary for:
| Need | Skill instead |
|---|
| Authorized GraphQL recon, introspection abuse, node BOLA | graphql-and-hidden-parameters |
| OpenAPI/REST operation prose and examples | api-documentation-writing |
JSON Schema / OpenAPI components/schemas design | json-schema-design |
| Resolver authz, limits, tests, reliability | code-quality-standards |
Repo Config First
Repo stack and neighboring types outrank defaults below.
- Stack: Apollo, Yoga, Hot Chocolate, graphql-java, Absinthe, Hasura, federation
- Source of truth: SDL-first vs code-first vs generated — edit only the authority
- Codegen: client/server configs, fragment policy, scalar maps
- Conventions:
PascalCase types, camelCase fields, layout, @auth/@deprecated/@key
- Pagination & errors: Relay vs offset; stable
extensions.code taxonomy
- Auth model: context + field directives vs resolver-only — do not fork
- Neighbors: copy 2–3 mature domains for IDs, inputs, mutation payloads
Precedence: Follow the repo on conflict. Surface changes that break clients,
hide authz only via “secret” fields, or diverge published schema from runtime.
Workflow
- Map domain — resources, ownership, read vs write, clients.
- Inventory schema — types, roots, scalars, deprecations, federation keys.
- Model reads — explicit object types; interfaces/unions only when polymorphism is real.
- Nullability —
Type! only when always provided on promised success; list forms
([Item!]! vs [Item]!) chosen intentionally (empty vs null list).
- Inputs/mutations — separate
CreateXInput/UpdateXInput; never reuse output
types as inputs; prefer …Payload (entity, userErrors) for extensibility.
- Pagination — match repo; growing public lists → cursor/Relay + page-size caps.
- IDs — stable opaque IDs (Relay global ID or UUID/ULID), not raw internal ints.
- Errors — document GraphQL errors vs field-null +
extensions; keep code stable.
- Evolve — add optional fields/args;
@deprecated(reason:) with replacement;
no silent renames or nullability tightenings without dual-run/version plan.
- Verify — schema lint, codegen, resolver tests; authz/complexity via
code-quality-standards. Live security testing → graphql-and-hidden-parameters.
Design Rules (defaults when repo is silent)
| Area | Prefer |
|---|
| Naming | Noun types; clear mutations (updateOrderStatus) |
| Inputs | Dedicated input objects; sparse documented custom scalars |
| Enums | Machine values; document tolerance for additive future values |
| Descriptions | Non-obvious elements; prose quality → api-documentation-writing |
| Lists | Connections or hard limits — no unbounded root lists |
| N+1 | Assume DataLoader/batching for list→child fields |
Good / Bad Examples
Good
type Order { id: ID!, note: String, items: [OrderItem!]! }
type Query { order(id: ID!): Order }
input UpdateOrderInput { id: ID!, note: String }
type UpdateOrderPayload { order: Order, userErrors: [UserError!]! }
type Mutation { updateOrder(input: UpdateOrderInput!): UpdateOrderPayload! }
Bad
type Query { orders: [Order!]! }
type Order { note: String! }
type Mutation { updateOrder(order: OrderInput!): Order }
input OrderInput { id: ID, totalCents: Int, isAdmin: Boolean }
Good deprecation: dual field + @deprecated(reason: "Use displayName…").
Bad: rename in place with no dual field or sunset.
Routing
| Situation | Primary | Helper |
|---|
| GraphQL schema shape, nullability, connections, mutations | This skill | — |
| Authorized live GraphQL testing (introspect, BOLA, batching) | graphql-and-hidden-parameters | this when hardening schema |
| Description prose quality | api-documentation-writing | this for type graph |
| REST/JSON Schema / OpenAPI models | json-schema-design | this only for GraphQL |
| Resolvers, authz, validation, tests, query limits | code-quality-standards | always on implementation |
graphql-and-hidden-parameters: recon/abuse of live GraphQL; return here for schema fixes.
api-documentation-writing: description quality; this skill owns SDL structure.
json-schema-design: REST/event JSON — do not force OpenAPI idioms onto GraphQL.
code-quality-standards: resolver authz, depth/complexity, DataLoader, tests,
no secrets in error extensions.
Checklist