Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Introduction

@frame/events is the centralized repository of integration events for the FRAME ecosystem. Every event that crosses a domain module boundary lives here — never inside the module that emits it.

Domain modules in apps/nest must not import one another directly. They still need to communicate sometimes: the users module needs to notify the notifications module when a user registers.

Without @frame/events, the only alternative would be for notifications to import from users — a direct coupling that makes it impossible to extract modules as independent microservices.

graph LR
    A[UsersModule] -- "UserRegisteredEvent" --> B[@frame/events]
    B -- "typed contract" --> C[NotificationsModule]
    B -- "typed contract" --> D[AdminModule]

    style B fill:#336699,color:#fff,stroke:#225588

@frame/events acts as the neutral layer between modules: the emitter publishes a contract, the consumer subscribes to that contract — neither knows the other’s implementation.

Not every event belongs here. The distinction is clear:

TypeWhere it livesWho consumes it
Domainsrc/modules/<mod>/v1/domain/events/Only within the same module
Integration@frame/events/src/<domain>/Any module or microservice

This package is the foundation that enables migration without a rewrite. When a module is extracted as a microservice, the event contracts already exist and are framework-agnostic. Only the EventBus transport changes (in-process → RabbitMQ/Kafka).

See Event Architecture for the contract structure that supports that path.

The package has a single runtime dependency: zod. It does not depend on NestJS, @nestjs/cqrs, or any other framework — the contracts are portable to any context.