Auto-Discovery
Learn how Nitro GraphQL automatically discovers and loads your GraphQL schemas, resolvers, and directives.
How Auto-Discovery Works
Nitro GraphQL scans your project at build time and during development to find:
- Schema files:
*.graphql - Resolver files:
*.resolver.ts - Directive files:
*.directive.ts - Client queries:
*.graphqlin client directories
All discovered files are automatically loaded and merged into your GraphQL server.
File Naming Conventions
Schema Files
Pattern: *.graphql
Location: server/graphql/**/*.graphql
Examples:
✅ server/graphql/schema.graphql
✅ server/graphql/user.graphql
✅ server/graphql/users/user.graphql
✅ server/graphql/posts/post.graphql
❌ server/graphql/schema.gql (wrong extension)
❌ server/api/schema.graphql (wrong directory)Resolver Files
Pattern: *.resolver.ts
Location: server/graphql/**/*.resolver.ts
Examples:
✅ server/graphql/hello.resolver.ts
✅ server/graphql/users/user.resolver.ts
✅ server/graphql/users/queries.resolver.ts
✅ server/graphql/users/mutations.resolver.ts
❌ server/graphql/user-resolver.ts (wrong pattern)
❌ server/graphql/user.ts (missing .resolver)Named Exports Required
Resolver files MUST use named exports:
// ✅ Correct
export const userQueries = defineQuery({...})
// ❌ Wrong - won't be discovered
export default defineQuery({...})Directive Files
Pattern: *.directive.ts
Location: server/graphql/**/*.directive.ts
Examples:
✅ server/graphql/directives/auth.directive.ts
✅ server/graphql/directives/cache.directive.ts
✅ server/graphql/auth.directive.tsClient Query Files (Nuxt)
Pattern: *.graphql
Location: app/graphql/**/*.graphql (Nuxt) or graphql/**/*.graphql (Nitro)
Examples:
✅ app/graphql/queries.graphql
✅ app/graphql/users/get-users.graphql
✅ app/graphql/users/create-user.graphqlDirectory Structure
Recommended Structure
server/
└── graphql/
├── schema.graphql # Root schema
├── users/
│ ├── user.graphql # User types
│ ├── queries.resolver.ts # User queries
│ ├── mutations.resolver.ts # User mutations
│ └── types.resolver.ts # User field resolvers
├── posts/
│ ├── post.graphql
│ └── post.resolver.ts
└── directives/
├── auth.directive.ts
└── cache.directive.tsMinimal Structure
server/
└── graphql/
├── schema.graphql
└── hello.resolver.tsLarge Project Structure
server/
└── graphql/
├── schema.graphql
├── auth/
│ ├── user.graphql
│ ├── user.resolver.ts
│ ├── session.graphql
│ └── session.resolver.ts
├── content/
│ ├── post.graphql
│ ├── post.resolver.ts
│ ├── comment.graphql
│ └── comment.resolver.ts
└── directives/
├── auth.directive.ts
├── permission.directive.ts
└── cache.directive.tsScanning Behavior
Build Time
During pnpm build:
- Scans
server/graphql/for.graphqlfiles - Merges all schemas into a unified schema
- Scans
server/graphql/for.resolver.tsfiles - Parses resolvers using
oxc-parser - Generates virtual imports for schemas and resolvers
- Generates TypeScript type definitions
Development Mode
During pnpm dev:
- Initial scan on startup (same as build)
- Watches for file changes
- Hot-reloads on schema/resolver changes
- Regenerates types automatically
File Watching
The dev server watches for changes in:
server/graphql/**/*.graphqlserver/graphql/**/*.resolver.tsserver/graphql/**/*.directive.ts
Changes trigger automatic reload and type regeneration.
Nuxt Layers Support
Nitro GraphQL supports Nuxt layers with automatic multi-layer scanning.
Example
// nuxt.config.ts
export default defineNuxtConfig({
extends: ['./layers/base', './layers/auth'],
modules: ['nitro-graphql/nuxt'],
})Layer Structure
project/
├── layers/
│ ├── base/
│ │ └── server/
│ │ └── graphql/
│ │ ├── schema.graphql # ← Discovered
│ │ └── posts.resolver.ts # ← Discovered
│ └── auth/
│ └── server/
│ └── graphql/
│ ├── user.graphql # ← Discovered
│ └── user.resolver.ts # ← Discovered
└── server/
└── graphql/
├── schema.graphql # ← Discovered
└── app.resolver.ts # ← DiscoveredAll schemas and resolvers from all layers are automatically discovered and merged!
Layer Priority
When extending multiple layers:
- Base layers are loaded first
- Extended layers override base layers
- App-level files override all layers
// Base layer
export const userQueries = defineQuery({
users: () => [{ id: '1', name: 'Base User' }],
})
// App layer (overrides base)
export const userQueries = defineQuery({
users: () => [{ id: '1', name: 'App User' }], // ← This wins
})Virtual Imports
Discovered files are exposed via virtual imports (for internal use):
import directives from '#nitro-internal-virtual/server-directives'
import resolvers from '#nitro-internal-virtual/server-resolvers'
// Virtual import - DO NOT use directly
import schemas from '#nitro-internal-virtual/server-schemas'These are used internally by the GraphQL server setup.
Resolver Scanning
Resolver files are parsed using oxc-parser to extract exports.
What Gets Scanned
The scanner looks for named exports using these functions:
defineResolverdefineQuerydefineMutationdefineTypedefineSubscriptiondefineDirective
Example
// server/graphql/users.resolver.ts
export const userQueries = defineQuery({
users: () => [], // ← Discovered
})
export const userMutations = defineMutation({
createUser: () => ({}), // ← Discovered
})
// This won't be discovered (not using a define function)
export function someHelper() {}Generated virtual import:
// Virtual: #nitro-internal-virtual/server-resolvers
import { userMutations, userQueries } from './server/graphql/users.resolver.ts'
export default [
userQueries,
userMutations,
]Custom Paths
You can customize discovery paths:
// nitro.config.ts
export default defineNitroConfig({
graphql: {
framework: 'graphql-yoga',
paths: {
serverGraphql: 'src/server/graphql', // Custom server path
clientGraphql: 'src/client/graphql', // Custom client path
},
},
})Learn More
See the Path Customization Guide for advanced configuration.
Debugging Discovery
Check Generated Files
Look at auto-generated files to see what was discovered:
.nitro/
└── graphql/
├── schema.ts # All discovered schemas
└── resolvers.ts # All discovered resolversEnable Debug Logging
// nitro.config.ts
export default defineNitroConfig({
graphql: {
framework: 'graphql-yoga',
},
devtools: { enabled: true },
})Check console output during build:
✔ Discovered 3 schema files
✔ Discovered 5 resolver files
✔ Discovered 2 directive filesCommon Issues
File not discovered:
- Check file extension (
.graphql,.resolver.ts,.directive.ts) - Verify file location (
server/graphql/**/*) - Ensure named exports in resolvers
- Restart dev server
Resolver not loaded:
- Must use
define*functions (defineQuery, etc.) - Must be named export (not default)
- Check for syntax errors
Schema not merged:
- Check for GraphQL syntax errors
- Verify file has
.graphqlextension - Ensure proper
extend typeusage
Performance Considerations
Build Performance
Auto-discovery is fast:
- Small project (10 files): ~50ms
- Medium project (100 files): ~200ms
- Large project (500 files): ~500ms
Development Performance
File watching is efficient:
- Only watches
server/graphql/directory - Debounced reload (300ms)
- Incremental type generation
Optimization Tips
- Organize files logically - Grouped files are easier to scan
- Avoid deep nesting - Keep directory depth reasonable
- Use consistent naming - Helps with caching