Documentation/Learn/Project Structure
In this section

Project Structure

A reference layout for a Titan-based project. The Omnitron monorepo itself follows this shape; consumer projects do not need to be a monorepo to use the same conventions.

Single-app layout

my-app/
  • src/
    • modules/
      • users/
        • users.service.ts
        • users.module.ts
        • users.types.ts
      • orders/
    • app.module.ts — Root module that imports the rest
    • main.ts — Application.create + start
  • tsconfig.json
  • package.json

Monorepo layout

For multi-service projects, mirror the Omnitron monorepo:

my-monorepo/
  • apps/
    • api/ — Titan service exposed over HTTP/WS
    • worker/ — Titan service exposed over TCP only
    • web/ — React frontend (Prism + netron-react)
  • packages/
    • shared-types/ — Service interfaces shared by all apps
    • shared-modules/ — Reusable Titan modules
  • pnpm-workspace.yaml
  • turbo.json

pnpm-workspace.yaml

packages:
  - apps/*
  - packages/*

Sharing service types

Service interfaces should live in a shared package so both the server implementation and the client queryInterface<T>() call see the same type:

packages/shared-types/
  • src/
    • users.contract.ts — interface UsersContract { … }
    • orders.contract.ts
  • package.json

The server class implements the contract; the client parameterises queryInterface<UsersContract>() against it.

Configuration

Titan's ConfigModule reads from any combination of files, env vars, and schema-validated overrides. A typical project:

my-app/
  • config/
    • default.yaml — Defaults that apply everywhere
    • development.yaml — Local-dev overrides
    • production.yaml — Prod overrides
  • src/
    • app.module.ts — Root module and configuration registration

See ConfigModule for configuration sources, validation and precedence.

Conventions

  • Module per bounded context. Group services, repositories, and schemas by domain, not by layer.

  • Contracts in a shared package. Keep *.contract.ts files free of runtime imports so the browser bundle does not pull in the server.

  • One main.ts per app. The root file boots Application.create; it should be the only entrypoint that performs side effects at import time.