All skills
apollographql avatar

/graphql-schema

@79d2b07 official
by Apollo GraphQLapollographql/skills115 stars
13

Guide for designing and changing GraphQL schemas following industry best practices. Use this skill whenever you create or edit GraphQL SDL, such as a `schema.graphql` file or `typeDefs`, including when: (1) designing a new GraphQL schema or API, (2) adding or changing types, fields, arguments, mutations, or descriptions in an existing schema, (3) reviewing existing schema for improvements, (4) deciding on type structures or nullability, (5) implementing pagination or error patterns, (6) ensuring security in schema design.

Use this Skill: https://skilld.dev/gh/apollographql/skills/graphql-schema

This session only. Nothing lands on disk.

referencesnaming.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Naming Conventions

This reference covers naming conventions for GraphQL schemas. Consistent naming makes APIs intuitive and self-documenting.

Table of Contents

General Principles

  1. Be Descriptive - Names should clearly indicate purpose
  2. Be Consistent - Follow the same patterns throughout
  3. Use Domain Language - Match business terminology
  4. Avoid Abbreviations - Prefer createdAt over crtAt
  5. Think Client-Side - Name from consumer's perspective

Types

Object Types: PascalCase

Use singular nouns in PascalCase:

# Correct
type User { ... }
type BlogPost { ... }
type ShoppingCart { ... }
type PaymentMethod { ... }

# Incorrect
type user { ... }        # lowercase
type Users { ... }       # plural
type blog_post { ... }   # snake_case

Interface Types: PascalCase

Use adjectives or nouns describing capability:

interface Node { ... }
interface Timestamped { ... }
interface Searchable { ... }
interface Commentable { ... }

Union Types: PascalCase

Use nouns or compound names:

union SearchResult = User | Post | Comment
union MediaContent = Image | Video | Audio
union NotificationTarget = User | Group | Channel

Fields

Object Fields: camelCase

Use camelCase, typically nouns or noun phrases:

type User {
  id: ID!
  firstName: String!
  lastName: String!
  emailAddress: String!
  createdAt: DateTime!
  isActive: Boolean!
}

Boolean Fields

Prefix with is, has, can, or should:

type User {
  isActive: Boolean!
  isVerified: Boolean!
  hasSubscription: Boolean!
  canEdit: Boolean!
  shouldNotify: Boolean!
}

type Post {
  isPublished: Boolean!
  isArchived: Boolean!
  hasFeaturedImage: Boolean!
}

Collection Fields

Use plural nouns:

type User {
  posts: [Post!]!
  followers: [User!]!
  notifications: [Notification!]!
}

type Query {
  users: [User!]!
  allPosts: [Post!]!
}

Relationship Fields

Name based on the relationship:

type Post {
  author: User!         # Not: user, createdBy
  comments: [Comment!]!
  tags: [Tag!]!
}

type Comment {
  post: Post!           # Parent reference
  author: User!
  replies: [Comment!]!  # Child reference
}

Computed Fields

Name by what they return, not how they're computed:

type User {
  fullName: String!        # Not: getFullName, computedName
  postCount: Int!          # Not: calculatePostCount
  recentActivity: [Activity!]!
}

Arguments

Argument Names: camelCase

type Query {
  user(id: ID!): User
  users(first: Int, after: String): UserConnection!
  search(query: String!, filters: SearchFilters): [SearchResult!]!
}

Common Argument Patterns

# Single item lookup
user(id: ID!): User
post(slug: String!): Post

# Filtering
users(role: Role, isActive: Boolean): [User!]!

# Pagination
posts(first: Int, after: String): PostConnection!
posts(last: Int, before: String): PostConnection!

# Sorting
posts(orderBy: PostOrderBy): [Post!]!

# Search
search(query: String!): [SearchResult!]!

Avoid Generic Names

# Avoid
posts(filter: JSON)
users(options: Options)

# Prefer
posts(status: PostStatus, authorId: ID)
users(role: Role, createdAfter: DateTime)

Enums

Enum Names: PascalCase

enum UserRole { ... }
enum OrderStatus { ... }
enum SortDirection { ... }

Enum Values: SCREAMING_SNAKE_CASE

enum UserRole {
  ADMIN
  MODERATOR
  MEMBER
  GUEST
}

enum OrderStatus {
  PENDING_PAYMENT
  PAYMENT_RECEIVED
  PROCESSING
  SHIPPED
  DELIVERED
  CANCELLED
  REFUNDED
}

enum SortDirection {
  ASC
  DESC
}

Mutations

Mutation Names: verbNoun

Use action verbs followed by the subject:

type Mutation {
  # Create operations
  createUser(input: CreateUserInput!): User!
  createPost(input: CreatePostInput!): Post!

  # Update operations
  updateUser(input: UpdateUserInput!): User!
  updatePost(input: UpdatePostInput!): Post!

  # Delete operations
  deleteUser(id: ID!): DeleteUserPayload!
  deletePost(id: ID!): DeletePostPayload!

  # Domain-specific operations
  publishPost(id: ID!): Post!
  archivePost(id: ID!): Post!

  sendMessage(input: SendMessageInput!): Message!

  addItemToCart(input: AddItemInput!): Cart!
  removeItemFromCart(itemId: ID!): Cart!

  followUser(userId: ID!): FollowPayload!
  unfollowUser(userId: ID!): UnfollowPayload!
}

Common Verb Patterns

Operation Verbs
Create create, add, register, submit
Read get, fetch, load (avoid in mutations)
Update update, edit, modify, set
Delete delete, remove, archive
State change publish, approve, reject, cancel
Relationships add, remove, link, unlink
Actions send, invite, follow, like

Input Types

Input Type Names

Use the mutation name + Input:

input CreateUserInput {
  email: String!
  name: String!
}

input UpdateUserInput {
  id: ID!
  email: String
  name: String
}

input SendMessageInput {
  recipientId: ID!
  body: String!
}

Payload Types

Use the mutation name + Payload or Result:

type DeleteUserPayload {
  success: Boolean!
  deletedUserId: ID
}

type FollowUserPayload {
  follower: User!
  followee: User!
}

Anti-Patterns

Don't Use Hungarian Notation

# Avoid
type TUser { ... }
type UserType { ... }
strName: String!
intAge: Int!

# Prefer
type User { ... }
name: String!
age: Int!

Don't Use Redundant Prefixes

# Avoid
type User {
  userId: ID!
  userName: String!
  userEmail: String!
}

# Prefer
type User {
  id: ID!
  name: String!
  email: String!
}

Don't Expose Implementation Details

# Avoid
type User {
  mysql_id: Int!
  redis_cache_key: String!
  getDerivedStateFromProps: JSON!
}

# Prefer
type User {
  id: ID!
  # Internal details should not appear in schema
}

Don't Use Vague Names

# Avoid
type Query {
  getData: JSON
  getInfo(type: String): JSON
  fetch(params: JSON): JSON
}

# Prefer
type Query {
  userProfile(userId: ID!): UserProfile
  orderHistory(first: Int): OrderConnection!
  searchProducts(query: String!): [Product!]!
}

Don't Mix Conventions

# Avoid: inconsistent naming
type User {
  firstName: String!    # camelCase
  last_name: String!    # snake_case
  EmailAddress: String! # PascalCase
}

# Prefer: consistent camelCase
type User {
  firstName: String!
  lastName: String!
  emailAddress: String!
}

Source: SKILL.md on GitHub

No alerts1d5 checks · Risk SAFE
  • Gen Agent Trust Hub1d

    The skill is a comprehensive guide for GraphQL schema design, providing best practices for types, naming, pagination, error handling, and security. It is purely documentation and contains no executable code or malicious instructions.

  • Socket1d

    No alerts

  • Snyk1d

    Risk: LOW · No issues

  • Runlayer7mo

    1/6 files flagged

  • ZeroLeaks5mo

    1 finding · Score: 86/100

Signed by skilld at 79d2b07. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 days ago
What it can do
Runs commands
compatibility
Any GraphQL implementation (Apollo Server, graphql-js, Yoga, etc.)
metadata
{
  "author": "apollographql",
  "version": "1.0.2"
}
All 1 allowed tools
Bash(npm:*) Bash(npx:*) Read Write Edit Glob Grep
  • Security
  • graphql
  • schema-design
  • api-design
  • apollo
  • nullability
  • pagination
  • mutations
  • type-design
  • backwards-compatibility

README badge

README badge for apollographql/skills/graphql-schema

Instructional skill covering GraphQL schema design best practices, including type definition patterns, nullability rules, pagination, error handling, and security considerations. Applicable to any GraphQL implementation (Apollo Server, graphql-js, Yoga) and targets decisions around type structures, backwards compatibility, and API usability.

Generated from the current SKILL.md.

Does this skill work with any GraphQL server library?
Yes. The skill is compatible with any GraphQL implementation including Apollo Server, graphql-js, Yoga, and others. It provides design guidance independent of server framework.
What topics does this skill cover?
The skill covers type design, nullability rules, input vs output types, interfaces, unions, pagination patterns, error modeling, security best practices, naming conventions, and mutation design.
Is this for existing schema review or new schema design?
Both. The skill applies when designing a new GraphQL schema, reviewing and improving existing schemas, deciding on type structures, or implementing specific patterns like pagination or error handling.
Does this include code generation or validation tools?
No. This skill is a design guide with reference documentation and best practices. It does not generate or validate schemas automatically.

Generated from the current SKILL.md. These answers refresh after source changes.