Skip to main content

Extending the GraphQL API

This guide explains how to add new queries, mutations, types, and permissions to the GraphQL API.

Architecture Overview

The GraphQL implementation is split between two packages:

PackagePurpose
packages/shared-graphql/Schema definitions (.graphql files), generated types, authorization helpers
apps/web/src/lib/graphql/Resolvers, server configuration, Apollo Client

Adding a New Domain

To add a new domain (e.g., project/):

1. Create the Schema

Create packages/shared-graphql/src/schemas/project/schema.graphql with type definitions, inputs, responses, and query/mutation extensions.

2. Update Codegen Configuration

Add the schema path to packages/shared-graphql/codegen.ts in the schema array.

3. Generate Types

Run nx generate shared-graphql to regenerate TypeScript types.

4. Update Schema Loader

Add the new schema to apps/web/src/lib/graphql/schema.ts.

5. Create Resolvers

Create apps/web/src/lib/graphql/project/resolvers.ts with resolver implementations.

6. Register Resolvers

Add resolvers to apps/web/src/lib/graphql/resolvers.ts.

Adding a New Type

  1. Define TypeScript type in packages/shared-types/src/lib/core.ts
  2. Add GraphQL type to appropriate .graphql file in packages/shared-graphql/src/schemas/
  3. Run nx generate shared-graphql to regenerate types using GraphQL Code Generator
  4. Implement resolvers if needed

Adding a New Query

  1. Add query definition to the appropriate .graphql schema file using extend type Query
  2. Run nx generate shared-graphql
  3. Implement resolver in the domain's resolvers.ts
  4. Register in main resolvers.ts

Adding a New Mutation

  1. Add mutation definition to the appropriate .graphql schema file using extend type Mutation
  2. Run nx generate shared-graphql
  3. Implement resolver with input validation
  4. Register in main resolvers.ts

Adding a New OAuth Scope

1. Update Scope Type

Add the new slug to the Permission union in packages/shared-types/src/lib/core.ts, then create it in the WorkOS dashboard and attach it to the roles that should hold it (mirroring ROLE_PERMISSIONS).

2. Update Default Scopes (Optional)

There is no default-grant list: a permission reaches a session only because WorkOS signed it into the access token. Keep slugs short — they ride in the session cookie.

3. Use in Resolvers

Use requirePermission(context, "your:permission") in resolver implementations.

NX Commands

CommandDescription
nx generate shared-graphqlGenerate TypeScript types from GraphQL schemas
nx build shared-graphqlBuild the shared-graphql package
nx lint shared-graphqlLint the shared-graphql package
nx test webTest the web app (includes GraphQL resolver tests)

Best Practices

  1. Keep schemas in shared-graphql - Schema definitions should be in packages/shared-graphql/src/schemas/
  2. Use .graphql files - Keep schema definitions in .graphql files for better tooling
  3. Run generate after schema changes - Always run nx generate shared-graphql after modifying schemas
  4. Use response wrappers - Return { data, error } objects instead of throwing errors
  5. Validate inputs - Check all input fields and return clear error messages
  6. Authorize explicitly - Call requirePermission(); the @auth directive is documentation only
  7. Use database repositories - Put database logic in packages/shared-db, not resolvers

Reference Files

FilePurpose
packages/shared-graphql/src/types.tsContext type and authorization helpers
packages/shared-graphql/codegen.tsCode generation configuration
apps/web/src/lib/graphql/schema.tsSchema loader
apps/web/src/lib/graphql/resolvers.tsCombined resolvers
apps/web/src/lib/graphql/common/utils.tsHelper functions