VP

vp-implement-module

Standardizes the creation of new NestJS domain modules in the VoxPopuli backend.

Install

mkdir -p .claude/skills/vp-implement-module && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13276" && unzip -o skill.zip -d .claude/skills/vp-implement-module && rm skill.zip

Installs to .claude/skills/vp-implement-module

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use when creating a new NestJS module in the VoxPopuli backend - covers service, module, spec file, shared types, and AppModule wiring following project conventions
164 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • →Create a new NestJS module structure
  • →Implement an injectable service with JSDoc and strict TypeScript
  • →Configure a NestJS module with imports, providers, and exports
  • →Write Jest tests for the service using `Test.createTestingModule()`
  • →Wire the new module into `apps/api/src/app/app.module.ts`
  • →Add new interfaces to `libs/shared-types/src/lib/shared-types.ts`

How it works

The skill follows a predefined pattern to generate a new NestJS module, including its service, module, and test files, and integrates it into the main application module. It adheres to project-specific conventions for dependency injection and external calls.

Inputs & outputs

You give it
Request to create a new NestJS module
You get back
A new NestJS module with service, module, spec file, and shared types, wired into AppModule

When to use vp-implement-module

  • →Creating new domain modules
  • →Implementing backend services
  • →Adding new API features

About this skill

Implement NestJS Module (VoxPopuli)

Overview

Every backend module has the same shape: an injectable service, a module that exports it, a Jest spec, and wiring into AppModule. Third-party APIs and env vars each have their own checklists below.

Module Structure

apps/api/src/{name}/
  {name}.service.ts       # @Injectable(), constructor DI, JSDoc on public methods
  {name}.module.ts        # imports deps, provides + exports the service
  {name}.service.spec.ts  # Jest (not Vitest), Test.createTestingModule()
  {name}.controller.ts    # only if it exposes HTTP endpoints
  1. Shared request/response types go in libs/shared-types/src/lib/shared-types.ts.
  2. Write the service, module, and spec.
  3. Import the module in apps/api/src/app/app.module.ts (ConfigModule is already global).

Calling a Third-Party HTTP API

Use Node's native fetch (no axios or vendor SDK unless it's already in package.json), with AbortSignal.timeout().

  • Caching: if the call is an idempotent read of cacheable data (HN items, deterministic lookups), wrap it in CacheService.getOrSet(key, fetcher, ttl). If it generates fresh or large binary output (TTS audio, LLM generations), call it directly.
  • Errors: throw a typed error class from the service (e.g. TtsUpstreamError). The controller maps that class to 502 Bad Gateway with the upstream reason in the message, and everything else to 500. Never pass the upstream status straight to our client: an upstream 401 means our key is wrong, not the user's.
  • Config: the key and model come from ConfigService. Fail fast with a clear error if the key is missing.
  • LLM access: go through LlmService.getModel(). Never construct LangChain providers directly.

Reference implementation: apps/api/src/tts/tts.service.ts (Mistral Voxtral).

Testing it

Spy on the global fetch and return real Response objects. Never hit the real API from Jest, including "skipped" integration specs.

const fetchMock = jest
  .spyOn(global, 'fetch')
  .mockResolvedValue(
    new Response(JSON.stringify({ translations: [{ text: 'hola' }] }), { status: 200 }),
  );
afterEach(() => fetchMock.mockRestore());

it('maps upstream failures to the typed error', async () => {
  fetchMock.mockResolvedValueOnce(
    new Response(JSON.stringify({ message: 'quota' }), { status: 456 }),
  );
  await expect(service.translate('hi', 'ES')).rejects.toBeInstanceOf(TranslateUpstreamError);
});

Cover the request shape (URL, auth header, body), success parsing, an HTTP error, a non-JSON error body, and a missing key. Real-API checks belong to vp-e2e-verify, not the test suite.

Adding an Environment Variable

Add it in every one of these places:

FileWhat
apps/api/src/config/env.validation.ts@IsString() @IsOptional() field (class-validator, not Joi)
.env.exampleCommented placeholder with the default
render.yamlsync: false for secrets, value: for plain config
CLAUDE.mdEnvironment Variables section
docs/codebase-summary.mdEnv var table

When you remove or rename a var (or an accepted value, like a provider name), delete it from all of these too and tell the user to clean up the Render dashboard. Until they do, the old value is still deployed; see vp-complete-milestone §2b.

Test Setup Gotcha

Specs that transitively import LlmService or AgentService must mock the providers, because Jest can't load @langchain/* ESM:

jest.mock('../llm/providers/openrouter.provider', () => ({ OpenRouterProvider: jest.fn() }));
jest.mock('../llm/providers/claude.provider', () => ({ ClaudeProvider: jest.fn() }));
jest.mock('../llm/providers/mistral.provider', () => ({ MistralProvider: jest.fn() }));

Common Mistakes

  • Importing another module's service directly instead of through DI and module imports
  • Forgetting to export the service from its module
  • Using vi.fn() in API specs; the API uses Jest (jest.fn())
  • jest.mock('axios') or jest.mock('node-fetch'); spy on the global fetch instead
  • Adding an env var to env.validation.ts but not to render.yaml or .env.example

Before opening a PR, use vp-complete-milestone.

When not to use it

  • →When modifying existing modules
  • →When performing frontend work
  • →When working on an evaluation harness

Limitations

  • →It is not for modifying existing modules.
  • →It is not for frontend work.
  • →It is not for evaluation harness tasks.

How it compares

This skill automates the creation of a NestJS module following specific project conventions, ensuring consistency and proper integration within the VoxPopuli backend.

Compared to similar skills

vp-implement-module side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
vp-implement-module (this skill)06moNo flagsIntermediate
telegram-mini-app628moReviewAdvanced
stripe-integration484moNo flagsAdvanced
nodejs-backend-patterns124moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

telegram-mini-app

davila7

Expert in building Telegram Mini Apps (TWA) - web apps that run inside Telegram with native-like experience. Covers the TON ecosystem, Telegram Web App API, payments, user authentication, and building viral mini apps that monetize. Use when: telegram mini app, TWA, telegram web app, TON app, mini app.

62163

stripe-integration

wshobson

Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.

48165

nodejs-backend-patterns

wshobson

Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Use when creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.

1246

agent-dev-backend-api

ruvnet

Agent skill for dev-backend-api - invoke with $agent-dev-backend-api

318

shopify-apps

alinaqi

Shopify app development - Remix, Admin API, checkout extensions

19

ccxt-typescript

ccxt

CCXT cryptocurrency exchange library for TypeScript and JavaScript developers (Node.js and browser). Covers both REST API (standard) and WebSocket API (real-time). Helps install CCXT, connect to exchanges, fetch market data, place orders, stream live tickers/orderbooks, handle authentication, and manage errors. Use when working with crypto exchanges in TypeScript/JavaScript projects, trading bots, arbitrage systems, or portfolio management tools. Includes both REST and WebSocket examples.

15

Search skills

Search the agent skills registry