Skillshub apollo-server
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/apollographql/skills/apollo-server" ~/.claude/skills/comeonoliver-skillshub-apollo-server && rm -rf "$T"
manifest:
skills/apollographql/skills/apollo-server/SKILL.mdsource content
Apollo Server 5.x Guide
Apollo Server is an open-source GraphQL server that works with any GraphQL schema. Apollo Server 5 is framework-agnostic and runs standalone or integrates with Express, Fastify, and serverless environments.
Quick Start
Step 1: Install
npm install @apollo/server graphql
For Express integration:
npm install @apollo/server @as-integrations/express5 express graphql cors
Step 2: Define Schema
const typeDefs = `#graphql type Book { title: String author: String } type Query { books: [Book] } `;
Step 3: Write Resolvers
const resolvers = { Query: { books: () => [ { title: "The Great Gatsby", author: "F. Scott Fitzgerald" }, { title: "1984", author: "George Orwell" }, ], }, };
Step 4: Start Server
Standalone (Recommended for prototyping):
The standalone server is great for prototyping, but for production services, we recommend integrating Apollo Server with a more fully-featured web framework such as Express, Koa, or Fastify. Swapping from the standalone server to a web framework later is straightforward.
import { ApolloServer } from "@apollo/server"; import { startStandaloneServer } from "@apollo/server/standalone"; const server = new ApolloServer({ typeDefs, resolvers }); const { url } = await startStandaloneServer(server, { listen: { port: 4000 }, }); console.log(`Server ready at ${url}`);
Express:
import { ApolloServer } from "@apollo/server"; import { expressMiddleware } from "@as-integrations/express5"; import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer"; import express from "express"; import http from "http"; import cors from "cors"; const app = express(); const httpServer = http.createServer(app); const server = new ApolloServer({ typeDefs, resolvers, plugins: [ApolloServerPluginDrainHttpServer({ httpServer })], }); await server.start(); app.use( "/graphql", cors(), express.json(), expressMiddleware(server, { context: async ({ req }) => ({ token: req.headers.authorization }), }), ); await new Promise<void>((resolve) => httpServer.listen({ port: 4000 }, resolve)); console.log("Server ready at http://localhost:4000/graphql");
Schema Definition
Scalar Types
- 32-bit integerInt
- Double-precision floating-pointFloat
- UTF-8 stringString
- true/falseBoolean
- Unique identifier (serialized as String)ID
Type Definitions
type User { id: ID! name: String! email: String posts: [Post!]! } type Post { id: ID! title: String! content: String author: User! } input CreatePostInput { title: String! content: String } type Query { user(id: ID!): User users: [User!]! } type Mutation { createPost(input: CreatePostInput!): Post! }
Enums and Interfaces
enum Status { DRAFT PUBLISHED ARCHIVED } interface Node { id: ID! } type Article implements Node { id: ID! title: String! }
Resolvers Overview
Resolvers follow the signature:
(parent, args, contextValue, info)
- parent: Result from parent resolver (root resolvers receive undefined)
- args: Arguments passed to the field
- contextValue: Shared context object (auth, dataSources, etc.)
- info: Field-specific info and schema details (rarely used)
const resolvers = { Query: { user: async (_, { id }, { dataSources }) => { return dataSources.usersAPI.getUser(id); }, }, User: { posts: async (parent, _, { dataSources }) => { return dataSources.postsAPI.getPostsByAuthor(parent.id); }, }, Mutation: { createPost: async (_, { input }, { dataSources, user }) => { if (!user) throw new GraphQLError("Not authenticated"); return dataSources.postsAPI.create({ ...input, authorId: user.id }); }, }, };
Context Setup
Context is created per-request and passed to all resolvers.
interface MyContext { token?: string; user?: User; dataSources: { usersAPI: UsersDataSource; postsAPI: PostsDataSource; }; } const server = new ApolloServer<MyContext>({ typeDefs, resolvers, }); // Standalone const { url } = await startStandaloneServer(server, { context: async ({ req }) => ({ token: req.headers.authorization || "", user: await getUser(req.headers.authorization || ""), dataSources: { usersAPI: new UsersDataSource(), postsAPI: new PostsDataSource(), }, }), }); // Express middleware expressMiddleware(server, { context: async ({ req, res }) => ({ token: req.headers.authorization, user: await getUser(req.headers.authorization), dataSources: { usersAPI: new UsersDataSource(), postsAPI: new PostsDataSource(), }, }), });
Reference Files
Detailed documentation for specific topics:
- Resolvers - Resolver patterns and best practices
- Context and Auth - Authentication and authorization
- Plugins - Server and request lifecycle hooks
- Data Sources - RESTDataSource and DataLoader
- Error Handling - GraphQLError and error formatting
- Troubleshooting - Common issues and solutions
Key Rules
Schema Design
- Use ! (non-null) for fields that always have values
- Prefer input types for mutations over inline arguments
- Use interfaces for polymorphic types
- Keep schema descriptions for documentation
Resolver Best Practices
- Keep resolvers thin - delegate to services/data sources
- Always handle errors explicitly
- Use DataLoader for batching related queries
- Return partial data when possible (GraphQL's strength)
Performance
- Use
and@defer
for large responses@stream - Implement DataLoader to solve N+1 queries
- Consider persisted queries for production
- Use caching headers and CDN where appropriate
Ground Rules
- ALWAYS use Apollo Server 5.x patterns (not v4 or earlier)
- ALWAYS type your context with TypeScript generics
- ALWAYS use
fromGraphQLError
package for errorsgraphql - NEVER expose stack traces in production errors
- PREFER
for prototyping onlystartStandaloneServer - USE an integration with a server framework like Express, Koa, Fastify, Next, etc. for production apps
- IMPLEMENT authentication in context, authorization in resolvers