Skills graphql-schema
install
source · Clone the upstream repo
git clone https://github.com/apollographql/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/apollographql/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/graphql-schema" ~/.claude/skills/apollographql-skills-graphql-schema && rm -rf "$T"
manifest:
skills/graphql-schema/SKILL.mdsource content
GraphQL Schema Design Guide
This guide covers best practices for designing GraphQL schemas that are intuitive, performant, and maintainable. Schema design is primarily a server-side concern that directly impacts API usability.
Schema Design Principles
1. Design for Client Needs
- Think about what queries clients will write
- Organize types around use cases, not database tables
- Expose capabilities, not implementation details
2. Be Explicit
- Use clear, descriptive names
- Make nullability intentional
- Document with descriptions
3. Design for Evolution
- Plan for backwards compatibility
- Use deprecation before removal
- Avoid breaking changes
Quick Reference
Type Definition Syntax
""" A user in the system. """ type User { id: ID! email: String! name: String posts(first: Int = 10, after: String): PostConnection! createdAt: DateTime! }
Nullability Rules
| Pattern | Meaning |
|---|---|
| String | Nullable - may be null |
| String! | Non-null - always has value |
| [String] | Nullable list, nullable items |
| [String!] | Nullable list, non-null items |
| [String]! | Non-null list, nullable items |
| [String!]! | Non-null list, non-null items |
Best Practice: Use [Type!]! for lists - empty list over null, no null items.
Input vs Output Types
# Output type - what clients receive type User { id: ID! email: String! createdAt: DateTime! } # Input type - what clients send input CreateUserInput { email: String! name: String } # Mutation using input type type Mutation { createUser(input: CreateUserInput!): User! }
Interface Pattern
interface Node { id: ID! } type User implements Node { id: ID! email: String! } type Post implements Node { id: ID! title: String! }
Union Pattern
union SearchResult = User | Post | Comment type Query { search(query: String!): [SearchResult!]! }
Reference Files
Detailed documentation for specific topics:
- Types - Type design patterns, interfaces, unions, and custom scalars
- Naming - Naming conventions for types, fields, and arguments
- Pagination - Connection pattern and cursor-based pagination
- Errors - Error modeling and result types
- Security - Security best practices for schema design
Key Rules
Type Design
- Define types based on domain concepts, not data storage
- Use interfaces for shared fields across types
- Use unions for mutually exclusive types
- Keep types focused (single responsibility)
- Avoid deep nesting - flatten when possible
Field Design
- Fields should be named from client's perspective
- Return the most specific type possible
- Make expensive fields explicit (consider arguments)
- Use arguments for filtering, sorting, pagination
Mutation Design
- Use single input argument pattern:
mutation(input: InputType!) - Return affected objects in mutation responses
- Model mutations around business operations, not CRUD
- Consider returning a union of success/error types
ID Strategy
- Use globally unique IDs when possible
- Implement
interface for refetchabilityNode - Base64-encode compound IDs if needed
Ground Rules
- ALWAYS add descriptions to types and fields
- ALWAYS use non-null (!) for fields that cannot be null
- ALWAYS use [Type!]! pattern for lists
- NEVER expose database internals in schema
- NEVER break backwards compatibility without deprecation
- PREFER dedicated input types over many arguments
- PREFER enums over arbitrary strings for fixed values
- USE
type for identifiers, notID
orStringInt - USE custom scalars for domain-specific values (DateTime, Email, URL)