GraphQL
Refract’s API is GraphQL, built with Apollo Server on the backend and Apollo Client on the frontend. The schema is generated from the backend resolvers, and TypeScript hooks for the frontend are generated from that schema. Once this pipeline is set up, adding a new API operation is a well-defined 5-step process.How it works
- You write a resolver in
apps/backend/src/gql/. - Running
make gql-codegendumps the full schema to/shared/template.schema.graphql. - The frontend codegen reads that schema plus any
useQuery/useMutationcalls in the frontend source, and generatesapps/frontend/src/gql/hooks.ts— a fully typed file of React hooks. - Your React component imports and calls the generated hook. TypeScript ensures the component’s types stay in sync with the API.
codegen-verification job enforces this — if you forget to run codegen after a schema change, the job fails and tells you to commit the updated generated file.
Resolver structure
Resolvers in Refract follow a consistent shape. Here’s a real example — a query that fetches countries with Redis caching:- The resolver function (named after the operation, e.g.
fetchCountries) - A schema builder function (named
build<OperationName>Schema) - The parameter type, exported so tests can import it instead of redefining it
Middleware chain
Resolvers useresolveWithMiddlewares to enforce authentication and authorization before running business logic. A typical secured mutation looks like:
Mutation return types
Mutations always return a discriminated union:result field with whatever data the client needs.
Adding a new query or mutation
-
Create the resolver file
For a query:
apps/backend/src/gql/queries/fetchMyThing.tsFor a mutation:apps/backend/src/gql/mutations/createMyThing.tsExport the resolver function, the schema builder, and the params type: -
Add business logic to a utility
apps/backend/src/utilities/myThing.ts— pure function, no direct SDK calls: -
Register the schema builder
In
apps/backend/src/gql/index.ts, add your builder to the merged schema: -
Run codegen
This generates the updated
apps/frontend/src/gql/hooks.tswith a newuseFetchMyThingQueryhook. -
Use the hook in the frontend
-
Write a test
apps/backend/src/gql/queries/__tests__/fetchMyThing.spec.ts: -
Verify
What’s next?
- Architecture Overview — where GraphQL fits in the full request lifecycle.
- Tooling System — how the
toolsobject gets intocontext. - Testing — how to test resolvers and utility functions.