For the complete documentation index, see llms.txt. This page is also available as Markdown.

Module contract

The locations below are relative to the package repository root. Each rule states whether it belongs in package metadata, a module definition, navigation, or the module's supporting source directories.

Module structure and registration

Source location

A module should reside beneath the owning package's modules/module-name directory. Its entry point must be module.ts; supporting client, domain and server code belongs beneath the same module directory.

Example:

# package repository root
packages/@acme/warehousing/
└─ modules/
   └─ stock/
      ├─ module.ts
      ├─ client/
      ├─ domain/
      └─ server/

Module definition

A module definition must provide pageRoutes and apiDefinitions. The route collections must be objects and may be empty. The definition belongs in modules/module-name/module.ts.

Example:

Package registration

A module must be imported and included in the owning package's modules collection. Voyzu does not discover modules by scanning the package's modules directory. Registration belongs in the package-level voyzu.package.ts.

Example:

Page routes

User-interface capability

A module exposes its user-interface pages by registering them in the pageRoutes collection in the module's module.ts. This collection is the module's authoritative list of pages and allows Voyzu to compose routing, authorization, page metadata and navigation references into the application.

A module with no user-interface pages must define an empty pageRoutes object.

Route definitions

Each page route must define a stable id, a unique application path, a pageTitle and a React Page component. Dynamic URL segments must use the Next.js bracket convention. Page-route registration belongs in the module's module.ts; page components normally belong under the module's server/pages or client directory.

Example:

Authorization

A page route should declare its authentication and minimum-role requirements explicitly. A protected page must use one of the Voyzu surface roles. Authorization metadata belongs on the page-route entry in the module's module.ts.

Example:

Metadata

A page route may provide breadcrumbs, help, and framing metadata. These values must describe the route without introducing navigation paths that conflict with the route definition. This metadata belongs on the page-route entry in the module's module.ts. A helpPath must be relative to the voyzu.settings.helpBaseUrl declared by the owning package.

Example:

See Documentation and help for the package-level help setting and publishing pattern.

Package navigation must refer to a module page by its route id. A module must not require navigation to be usable; modules may be API-only or server-only. Navigation definitions belong in the owning package's navigation directory, not in the module definition.

Example:

API routes

API capability

A module exposes its HTTP API by registering its routes in the apiDefinitions collection in the module's module.ts. This collection is the module's authoritative list of endpoints and allows Voyzu to compose handlers and route matching into the application.

A module with no HTTP API must define an empty apiDefinitions object.

Route definitions

Each entry in apiDefinitions defines one HTTP endpoint. It must specify an HTTP method, a path relative to Voyzu's /api base path and an asynchronous handler. The combination of method and path must be unique across the composed application.

API routes must follow REST principles. Paths must identify resources using nouns, HTTP methods must express the operation using their standard semantics, and handlers must return appropriate HTTP status codes. Route registration belongs in the module's module.ts; handler implementations belong under server/api.

Example:

Request and response contracts

An API route should use explicit DTOs for request bodies, path parameters, query parameters and responses. Shared Voyzu request and error DTOs should be reused rather than redefined. Domain DTOs belong in the owning package's types area and must be exposed through a public export when other packages consume them.

Example:

Module implementation

Validation

A module must validate data at the appropriate transport, service and persistence boundaries. Validation failures must use the standard Voyzu error contracts. Business-input validators belong under server/lib; handler-level parsing belongs under server/api.

Example:

See the pattern Validation layers

Business rules

Business rules must reside in the module's domain or service layer rather than in React pages or HTTP route registration. Rule failures must produce stable, meaningful Voyzu business errors. Rules belong under domain or server/lib.

Example:

Server boundary

Server-only code must remain under the module's server boundary and must not be imported by client components. Client-safe entry points must not re-export database, credential or server-only functionality. The boundary is expressed by separate client and server directories and entry points.

SSR page components may import server-only. A Node-safe service barrel used by tests and scripts must not re-export those pages; expose SSR pages through a separate page entry point.

Example:

Persistence

Database access must be isolated behind module-owned repositories or services. Pages and HTTP handlers must not issue ad hoc database queries. Repository code belongs under server/db; orchestration belongs under server/lib.

Example:

Auditing

A module that mutates auditable business data must use Voyzu's audit contracts and propagate the current actor and mutation context. Audit records must be written as part of the same business operation. Audit stamping normally occurs in the module's service layer before repository persistence.

Example:

Public module APIs

Module functionality intended for use by another package must be exported through a package-level public entry point. Consumers must not import private module files. The public entry point belongs in the providing module, and the export mapping belongs in the owning package's package.json.

Example:

Quality and guidance

Testing

A module should test its domain rules, request and response validation, and exposed service behaviour at the narrowest useful boundary. Repository outcomes should be verified through services rather than by testing private repositories directly. Tests should reside within the module or in the repository's corresponding package test area.

Example:

Voyzu patterns

A module should follow the established Voyzu patterns for data, APIs, application surfaces, validation, auditing, integration and testing unless the module documents a deliberate exception.

Example:

See the patterns for data, APIs, application surfaces, validation, auditing, and testing.

Reference package

The Voyzu Ice Creams package conforms to this contract and demonstrates many of the established module and application patterns in use.

View the Ice Creams reference package on GitHub

Last updated