A modern, lightweight, and opinionated boilerplate for building robust GraphQL APIs with Node.js and TypeScript. Designed for speed, type safety, and a seamless developer experience.
This repository provides a production-ready foundation for building modular GraphQL backends. It moves beyond a basic Node.js setup by integrating a schema-first workflow, automated type generation, and a feature-based architecture. Instead of wiring up standard middleware, you can focus on defining your schema and implementing business logic.
- Schema-First Workflow: Define your API in
.graphqlfiles and let the tooling generate the boilerplate. - Automated Type Generation: Ensures end-to-end type safety between your schema and resolvers.
- Feature-Based Architecture: Keep your codebase scalable and maintainable by organizing it into domain-driven modules.
- Built-in Endpoint Protection: Reusable guards for implementing authorization and access control.
- High-Performance Tooling: Pre-configured with Vitest for fast testing and ts-node for seamless TypeScript execution.
- Modern ESM & Tooling: Uses standard JavaScript modules, ESLint 9, and a modern
eslint.config.jsflat config.
- Runtime: Node.js (>= 20.19)
- Language: TypeScript 5.8
- GraphQL: GraphQL.js & GraphQL Codegen
- Server: Fastify
- Testing: Vitest
- Linting: ESLint 9 (with
@typescript-eslintand@stylistic)
- Node.js >= 20.19
- npm (or your preferred package manager)
git clone https://github.com/rahmanroman/node-graphql-backend.git
cd node-graphql-backend
npm installCreate a .env file for local development.
cp .env.example .envnpm run devThis command starts the server with hot-reloading, listening on http://localhost:3000.
Once the server is running, explore the API using the built-in GraphQL Playground available at:
You can write queries, mutations, and view the schema documentation directly in your browser.
This template uses a simple file-based data store located in the .data/ directory. The authors.json and books.json files serve as a mock database, allowing you to test the API without setting up an external database. The repositories in src/repositories/ are responsible for interacting with these files.
This project uses graphql-codegen to automatically generate TypeScript types from your GraphQL schemas. This ensures that your resolvers are always type-safe and consistent with your API definition.
To regenerate types after changing a .graphql file, run:
npm run codegenThe configuration can be found in codegen.yml.
You can protect your resolvers using composable guards. A guard is a higher-order function that wraps a resolver and can check for certain conditions (e.g., authentication) before executing it.
The hasToken guard in src/graphql/guards.ts provides an example:
// src/graphql/guards.ts
export const hasToken = (): Guard => next => (
root: unknown,
args: object,
context: Context,
info: GraphQLResolveInfo,
) => {
if (!context.token) throw new GraphQLError('Unauthorized');
return next(root, args, context, info);
};This can be applied in your feature's resolver map to protect specific queries or mutations.
Run the test suite using Vitest:
npm test├── .data/ # Mock JSON database files
│ ├── authors.json
│ └── books.json
├── src/
│ ├── features/ # Domain-driven modules (GraphQL schemas and resolvers)
│ │ ├── book/
│ │ └── author/
│ ├── repositories/ # Data access layer (e.g., database interactions)
│ │ ├── book.ts
│ │ └── author.ts
│ ├── graphql/ # GraphQL engine, root schema, guards, & generated types
│ ├── server/ # Server setup and configuration
│ └── index.ts # Application entry point
├── codegen.yml # GraphQL Code Generator config
├── eslint.config.js # Modern ESLint flat config
└── vitest.config.ts # Vitest configuration
This template uses ts-node for development and serving. For a production environment, it is best practice to compile the TypeScript code to JavaScript and run the output.
You could add a build script to your package.json:
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}And create a tsconfig.json that outputs the compiled files to a dist directory.
This project is licensed under the MIT License.
Built with ❤️ by Roman Rakhman