Imported from eleven-labs/nest-profiler (
AGENTS.md). Install upstream withnpx skills add eleven-labs/nest-profiler. Copyright stays with the author.
nest-profiler
Project overview
Open-source monorepo for the @eleven-labs/nest-profiler ecosystem: a Symfony Web Profiler-inspired toolkit for NestJS. It ships 14 publishable packages (@eleven-labs/nest-profiler core + 13 collector packages), a consuming example app (example-api), shared @repo/* workspace presets, an English-only Fumadocs site, and full CI / release automation to publish to npm.
Constraints:
- Open source, MIT licensed.
- Only Node
>=22.0.0is supported. No legacy Node 20, no.nvmrc. - Public package APIs must remain importable from the package root only.
- The documentation site targets package consumers, never maintainers of the monorepo itself.
Technical stack
NestJS + TypeScript packages, Jest for tests, ESLint + Prettier, Turborepo for task orchestration, Changesets for versioning and publishing, Fumadocs (Next.js + MDX) for the English-only documentation site. Exact versions live in the respective package.json files.
Shared ESLint / Prettier / TypeScript / Jest rules live in packages/configs/* and are consumed as @repo/* packages with workspace:*. Never duplicate compiler, lint, or test options downstream — extend the preset.
Architecture
The agent should introspect the workspace before editing; only the non-obvious rules are listed here.
packages/<name>is the only path for publishable packages. New packages mirror the shape ofpackages/nest-profiler.packages/configs/*are private@repo/*presets, never published.examples/apiis the consumer-side demonstration. It is in.changeset/config.json#ignoreand never enters the release flow.docs/is a Fumadocs site deployed to Vercel via Vercel's Git integration (no workflow in this repo), independently of package release.scripts/holds release helpers (changesets/*,absolutize-readme-images.ts), not runtime code. Repository labels are declarative (.github/labels.yml) and synced by therepo-config.ymlworkflow, while milestones are managed by hand in the GitHub UI; one-time GitHub setup is documented inMAINTAINERS.md.
Code conventions
- Public exports live exclusively in each package's
src/index.ts. Deep imports fromdist/or internal paths are not part of the public API. - Every public symbol that should appear in the API reference carries TSDoc comments —
<AutoTypeTable>reads them. - NestJS modules use
ConfigurableModuleBuilderwithforRoot/forRootAsync. Options expose anisGlobalflag forwarded asglobalon the returnedDynamicModule. - Publishable packages declare
"type": "commonjs","sideEffects": false,"engines.node": ">=22.0.0", and treat NestJS +reflect-metadata+rxjsas peer dependencies (and as devDependencies for local tests). - Tests live next to the source as
*.spec.tsand run under Jest withts-jest. - Documentation content is written in English only. Consumer documentation files use the explicit
.en.mdxsuffix, and the default language served by the site isen. - Any user-visible change to a publishable package requires a Changeset entry (
pnpm changeset).example-apiand@repo/*are excluded from publishing.
Available commands
The agent should read package.json for the full list of scripts. The conventions below describe when to use them, not which exist.
- Targeted iteration:
pnpm --filter @eleven-labs/<name> <script>(e.g.pnpm --filter @eleven-labs/nest-profiler test). - Cross-cutting actions live in root
package.jsonscripts (docs, example app, release, packing). Prefer them over recreating their command lines. - Do not invoke
turbo run …directly from new code or workflows — route through a root script.
Mandatory validation before delivery
Every change must pass:
pnpm format:checkpnpm lintpnpm typecheckpnpm testpnpm build
Add when the change touches the matching area:
pnpm docs:build— when editing anything underdocs/.pnpm pack:dry-run,pnpm publint, andpnpm attw— when editing a publishable package's manifest or its public exports.- Repeat the relevant suite under
nvm use 22thennvm use 24when the change is runtime-sensitive.
No change is considered ready while any required step fails.
Best practices
- SOLID and clear boundaries: each NestJS module exposes one responsibility, services are injected via tokens, options flow through
ConfigurableModuleBuilder. Avoid generic helper layers until two packages prove they are needed. - DRY across the workspace: shared lint / format / TypeScript rules live in the
@repo/*presets, never duplicated downstream. Shared release filters live in rootpackage.jsonscripts, not inside workflows. - KISS: a package should be obvious before it is clever. Prefer one explicit module + service pattern over abstract factories. Three similar lines beat a premature abstraction.
- Configurability: anything environment-specific is supplied by the consumer through module options (
forRoot/forRootAsync). Packages never readprocess.envdirectly — that decision belongs to the host application (examples/apishows the pattern). - Dependency hygiene: before adding a new runtime dependency, check whether NestJS,
rxjs, or an existing package already provides it. New dependencies must be actively maintained, lightweight, and declared in the correct bucket —peerDependenciesfor anything the consumer also installs. - Documentation in sync: any change to a publishable package's public API requires updating its
docs/content/docs/packages/<name>.en.mdxpage, itsapi-reference/<name>.en.mdxpage, and — where relevant — its tutorials.
Workflow
When adding a feature
- Identify the target package under
packages/<name>, or scaffold a new one when no existing package fits. - Implement the change in the appropriate file — service for runtime logic, builder for option contracts, module for wiring.
- Add or update
*.spec.tsnext to the code to cover the new behaviour. - Export anything intended for consumers from the package's
src/index.tsonly, and add TSDoc on every new public symbol. - If the feature is demonstrable, wire it into
examples/api. - Update the matching Fumadocs pages (package guide, API reference, tutorial) in English.
- Run the mandatory validation suite, then add
pnpm changeset.
When fixing a bug
- Write a failing
*.spec.tsthat reproduces the bug (TDD-first). - Fix the source. Do not bundle refactors or unrelated cleanup into a bug fix.
- Confirm error handling and any user-facing messages still match the public contract.
- Run the mandatory validation suite, then add
pnpm changesetwith apatchbump.
When refactoring
- Run
pnpm testbefore any edit to capture the current baseline. - Keep the public API stable —
src/index.tsexports and option types do not change in a refactor. - Stay within the existing architectural boundaries (packages vs configs vs examples vs docs).
- Coverage must not drop on touched packages.
- Run the mandatory validation suite.
- Add a Changeset only if any consumer-observable behaviour changed.