Skip to content

Introduction

HeryJs is a batteries-included framework built on top of NestJS. It is not a runtime library your app depends on forever — it is a generator you run once per resource, on top of a small set of shared building blocks (capabilities, tenancy, error handling, response envelope) that you do keep.

Generate once. The CLI scaffolds a resource — DTO, policy, service, controller, record loader, factory, view, test spec — and then it is done. There is no re-generation of an existing module, no drift between “what the blueprint says” and “what the code does,” because after generation the blueprint is no longer read by anything at runtime.

Own your code. Every file the generator writes is meant to be edited by hand afterward, like any other NestJS file. There is no decorator that reads the blueprint at request time, no proxy standing between your controller and the database. If you need to change how a resource behaves, you change the generated code directly.

A HeryJs project is split into four layers, by lifecycle rather than by theme — whether a piece of code is always present, optional, business-specific, or dev-only:

  • technical/ — the kernel, never optional: capabilities engine, teams, tenancy middleware, error handling, HTTP envelope, auth.
  • functional/ — one folder per business resource, each following the same shape: a .module.ts, .controller.ts, .service.ts, .policy.ts, .dto.ts and .spec.ts at minimum, named after the resource.
  • modules/ — what arrives through hery install and can be removed again: mail, storage, WebSockets, streaming.
  • devtools/ — the request inspector and test helpers, which never ship to production.

An architecture linter (dependency-cruiser, plus a Jest convention test) enforces the split in CI: the kernel never reaches into a domain or an optional module, no module reaches into another, nothing but a spec reaches into devtools/, and every resource folder carries the files this convention expects. See Project structure.

Every resource generated by hery generate is, by construction:

  • Multi-tenant — a tenant is resolved once per request and injected into every query for that resource, without the caller ever passing it explicitly.
  • Capability-checked — every route carries a @Capability(fn) decorator, or a @PublicRoute('<why>') stating why it cannot; a CI script fails the build on a route that carries neither.
  • Contract-bound on search — pagination limits, sortable fields and filterable fields are declared once in the blueprint; a shared query parser rejects anything outside that contract with a 400, instead of leaving each controller to reimplement its own validation.
  • Tested end to end — the generated spec boots the real app against a real database and proves the 403, the tenant boundary, and the agreement between the list route and the detail route. A domain without a spec fails the suite.

The kernel covers the backend core. Everything else is a module you install, and nothing you have not installed is in your dependency tree or your app module:

full-text and vector search on Elasticsearch, Meilisearch or pgvector · GraphQL · an MCP gateway for agents · WebSockets, server-sent events and a per-subscriber change feed · LiveKit audio and video · mail, SMS and push through one notifier · two-factor, social and enterprise sign-in · billing that mirrors a provider’s subscription · file storage on disk · an admin panel that builds itself from introspection.

The following pages go through each of these pieces in more depth.