File naming convention

Discovery is automatic. DocfyModule locates each controller's source file via Node's module cache.

Convention

Discovery is automatic. DocfyModule locates each controller's source file via Node's module cache and resolves the companion path: this works identically under ts-node (development) and compiled dist/ (production).

Controller fileCompanion file
users.controller.tsusers.controller.docs.ts
users.controller.jsusers.controller.docs.js

Barrel re-exports

Barrel re-exports

If your controller is also exported from a barrel index.ts, make sure the class is exported directly from its own module file. nestjs-docfy prefers .controller.ts over barrel files.

Not supported: the NestJS CLI's webpack: true build mode

If your nest-cli.json has "webpack": true under compilerOptions (the documented default for monorepos with multiple apps), nestjs-docfy will not work, and there is no configuration that makes it work. This is architectural, not a bug to be fixed:

  • Webpack inlines every module into a single bundle file and never populates Node's require.cache with one entry per original source file, which is what the discovery mechanism depends on. You'll see Could not locate source file for X for every controller with @WithDocs().
  • Even if that lookup is worked around (for example, by recovering the original path from the bundle's source map, skipping require.cache), there's an unavoidable second wall: a docs file required from outside the bundle creates a class object that is structurally different from the one the running app uses internally. Decorating that fresh copy has no effect on the document that SwaggerModule.createDocument() actually serves. This happens silently, with no error.
  • The only way around this would be for the controller file itself to import its .docs.ts companion (forcing webpack to bundle both together), which defeats the entire point of the convention: zero coupling between controller and documentation.

How to resolve it

If you need nestjs-docfy, disable webpack bundling: remove "webpack": true (or set it to false) in nest-cli.json. Under the default tsc-based compilation, every source file (including every *.controller.docs.ts) is compiled to its own .js in dist/, so require.cache naturally has one entry per file and discovery works.

If you can't turn off webpack, use the patch-spec command as an alternative flow.