install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/nestjs-config-module" ~/.claude/skills/intense-visions-harness-engineering-nestjs-config-module && rm -rf "$T"
manifest:
agents/skills/claude-code/nestjs-config-module/SKILL.mdsource content
NestJS Config Module
Manage environment config with ConfigModule.forRoot, ConfigService, and Joi schema validation
When to Use
- You need to load environment variables from
files and inject them into services.env - You want to validate that required environment variables are present at startup (fail-fast)
- You need a typed configuration service instead of raw
accessprocess.env - You want to organize configuration into namespaced sections (database, auth, mail)
Instructions
- Install and register:
npm install @nestjs/config
// app.module.ts @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, // no need to import in each module envFilePath: '.env', // default — loads .env validationSchema: Joi.object({ NODE_ENV: Joi.string().valid('development', 'production', 'test').required(), DATABASE_URL: Joi.string().required(), JWT_SECRET: Joi.string().min(32).required(), PORT: Joi.number().default(3000), }), }), ], }) export class AppModule {}
- Inject ConfigService:
@Injectable() export class DatabaseService { constructor(private config: ConfigService) { const url = this.config.get<string>('DATABASE_URL'); const port = this.config.get<number>('PORT', 3000); // with default } }
- Typed namespaced config with
:registerAs
// config/database.config.ts export default registerAs('database', () => ({ url: process.env.DATABASE_URL, maxConnections: parseInt(process.env.DB_MAX_CONNECTIONS ?? '10'), })); // app.module.ts ConfigModule.forRoot({ load: [databaseConfig] }) // inject constructor( @InjectConfig('database') private dbConfig: ConfigType<typeof databaseConfig> ) {} // or this.config.get('database.url')
- Validate with Joi (install separately:
):npm install joi
validationSchema: Joi.object({ DATABASE_URL: Joi.string().uri().required(), JWT_SECRET: Joi.string().min(32).required(), PORT: Joi.number().port().default(3000), });
- Multiple env files for environment-specific configs:
ConfigModule.forRoot({ envFilePath: ['.env.local', '.env'], // .env.local takes precedence });
Details
@nestjs/config is a thin wrapper around the dotenv package with NestJS-specific integration: DI injection, module-level encapsulation, and schema validation.
Fail-fast validation: When a
validationSchema is provided, ConfigModule validates all environment variables at application bootstrap. If required variables are missing or invalid, the process exits with a descriptive error before any service initializes. This prevents runtime errors from missing config deep in the request path.
: Makes isGlobal: true
ConfigModule available to all modules without explicit import. Since configuration is genuinely app-wide, this is almost always correct. Register it once in AppModule.
typing: The generic type is a hint only — TypeScript cannot verify that ConfigService.get<T>()
process.env.PORT is actually a number. Use parseInt() or the namespaced registerAs() approach with proper type coercion.
Testing: In tests, use
ConfigModule.forRoot({ envFilePath: '.env.test' }) or override with { provide: ConfigService, useValue: { get: jest.fn((key) => testValues[key]) } }.
Custom ConfigFactory pattern: For complex scenarios (secret manager, remote config), implement a
ConfigFactory function and return the config object from an async source. Use ConfigModule.forRootAsync({ useFactory: ... }) with injected HTTP clients or secret manager SDKs.
Source
https://docs.nestjs.com/techniques/configuration
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.