Pothos is a TypeScript-first GraphQL schema builder that emphasizes type safety and developer experience through a code-first approach. Unlike traditional GraphQL implementations that require separate schema definitions and resolver files, Pothos unifies everything in a single, type-safe API. It leverages TypeScript's type system to provide automatic inference across schema definitions, fields, arguments, and resolvers, eliminating the manual synchronization overhead common in GraphQL development.
The library's plugin architecture allows developers to extend functionality based on their stack requirements. The Prisma plugin ecosystem is particularly robust, offering generators that derive GraphQL types directly from Prisma schemas, utilities for building filter inputs compatible with Prisma's query API, and helpers for managing relations and CRUD operations. This integration handles common performance pitfalls like N+1 queries through field selection merging and batched findUnique operations.
Pothos has gained traction among teams building modern GraphQL APIs who prioritize type safety and want to avoid code generation for resolvers. It's particularly popular in TypeScript projects using Prisma as the ORM layer and implements the Relay specification natively, making it a strong choice for applications requiring cursor-based pagination and connection patterns. The library works with standard GraphQL.js schemas and integrates seamlessly with GraphQL servers like Apollo, GraphQL Yoga, and Express-GraphQL.
While still evolving (version 0.0.1 in npm, though the @pothos/core scoped package is mature), the ecosystem focuses on providing building blocks rather than full auto-generation, giving developers explicit control over their API surface while maintaining type safety guarantees throughout the stack.
import SchemaBuilder from '@pothos/core';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
const builder = new SchemaBuilder({
plugins: [],
});
builder.queryType({
fields: (t) => ({
user: t.field({
type: User,
args: {
id: t.arg.id({ required: true }),
},
resolve: async (parent, args) => {
return prisma.user.findUniqueOrThrow({
where: { id: String(args.id) },
});
},
}),
}),
});
const User = builder.objectRef<{ id: string; email: string; name: string | null }>('User').implement({
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
name: t.string({
nullable: true,
resolve: (user) => user.name,
}),
posts: t.field({
type: [Post],
resolve: (user) => {
return prisma.post.findMany({
where: { authorId: user.id },
});
},
}),
}),
});
const Post = builder.objectRef<{ id: string; title: string; content: string }>('Post').implement({
fields: (t) => ({
id: t.exposeID('id'),
title: t.exposeString('title'),
content: t.exposeString('content'),
}),
});
export const schema = builder.toSchema();Prisma-based GraphQL APIs: Teams using Prisma as their ORM can leverage Pothos plugins to automatically generate GraphQL types from their database schema while maintaining full control over exposed fields and implementing custom business logic in resolvers without manual type synchronization.
Type-safe API development: Projects requiring end-to-end type safety can use Pothos to ensure that schema changes propagate through resolvers automatically, with TypeScript catching mismatches at compile time rather than runtime, reducing bugs from schema-resolver drift.
Relay-compliant applications: Frontend applications using Relay for data fetching benefit from Pothos's built-in connection and node helpers, which implement cursor-based pagination, global object identification, and edge patterns without boilerplate.
Incremental GraphQL migrations: Existing REST APIs transitioning to GraphQL can adopt Pothos gradually, as its plugin system allows adding functionality like authorization, validation, or dataloader integration without rewriting the entire schema.
Multi-tenant or filtered APIs: Applications requiring complex filtering capabilities can use the Prisma utilities plugin to expose type-safe filter inputs (string contains, equals, numeric comparisons) that map directly to Prisma's where clauses, avoiding manual input type definitions.
npm install pothospnpm add pothosbun add pothos