Component Creator

When to use this skill

When the user requests the creation of new components for ORE Studio. Components in ORE Studio terminology, are the projects under the projects directory. Example of existing components: ores.accounts, ores.refdata.

Component split: api / core / service

Most domain components in ORE Studio are split into three sibling projects:

Project Role
ores.COMPONENT.api Public domain types, interfaces, generators, and messaging protocols. No heavy deps.
ores.COMPONENT.core Internal implementation: repositories, services, DB access. Depends on .api.
ores.COMPONENT.service Runnable service: message handlers, startup, hosting. Depends on .core.

Facet placement by split:

Facet api core service
domain    
generators    
messaging    
eventing    
repository    
service    
app    
config    

Typical CMake dependency chain:

  • ores.COMPONENT.api.lib links: ores.eventing.lib, ores.platform.lib (PUBLIC)
  • ores.COMPONENT.core.lib links: ores.COMPONENT.api.lib, ores.database.lib, sqlgen (PRIVATE)
  • ores.COMPONENT.service links: ores.COMPONENT.core.lib

Not every component needs all three parts. A pure lookup/reference component may only need .api; a component with no service boundary may stop at .core.

How to use this skill

Important: Use the codegen system to scaffold new components. Do not create files manually — the component profile in ores.codegen generates all boilerplate automatically and ensures consistency with the rest of the codebase.

  1. Gather information about the new component (name, purpose, etc).
  2. Decide which parts are needed (.api, .core, .service, or a subset).
  3. Create one component model JSON file per part.
  4. Run the code generator with the component profile for each part.
  5. Register each part in projects/CMakeLists.txt.
  6. Add the PlantUML diagram stub for each part.
  7. Build and test.

Detailed instructions

Step 1: Gather requirements

Before starting, gather the following information from the user:

  • Component name: the short name (e.g., trading for ores.trading.*).
  • Parts needed: which of .api, .core, .service are required.
  • Brief: a one-line description of the component.
  • Description: a longer description of the component's purpose and responsibilities.

Component names must follow the convention ores.COMPONENT where COMPONENT is all lower case and ideally just one word (though exceptions exist, e.g. ores.http.server). Each part is a separate project: ores.COMPONENT.api, ores.COMPONENT.core, ores.COMPONENT.service.

Step 2: Create the component model files

Create one JSON model file per part under projects/ores.codegen/models/COMPONENT/.

For ores.COMPONENT.api:

{
  "component": {
    "name": "COMPONENT.api",
    "full_name": "ores.COMPONENT.api",
    "brief": "Public API for COMPONENT",
    "description": "Domain types, generators, messaging protocols and eventing for COMPONENT."
  }
}

For ores.COMPONENT.core:

{
  "component": {
    "name": "COMPONENT.core",
    "full_name": "ores.COMPONENT.core",
    "brief": "Core implementation for COMPONENT",
    "description": "Repositories, services and database access for COMPONENT. Depends on ores.COMPONENT.api."
  }
}

For ores.COMPONENT.service (if needed):

{
  "component": {
    "name": "COMPONENT.service",
    "full_name": "ores.COMPONENT.service",
    "brief": "Service host for COMPONENT",
    "description": "Message handlers, startup and hosting for COMPONENT. Depends on ores.COMPONENT.core."
  }
}

Step 3: Run the code generator

From the projects/ores.codegen directory, use the matching profile for each part:

./run_generator.sh models/COMPONENT/ores_COMPONENT_api_component.json --profile component-api
./run_generator.sh models/COMPONENT/ores_COMPONENT_core_component.json --profile component-core
./run_generator.sh models/COMPONENT/ores_COMPONENT_service_component.json --profile component-service

Each profile generates files tailored to its role. The .api and .core profiles both produce 9 files; component-service produces 18:

Generated file api core service
CMakeLists.txt
src/CMakeLists.txt (deps vary per profile)
tests/CMakeLists.txt
modeling/CMakeLists.txt
include/ores.COMPONENT.PART/ores.COMPONENT.PART.hpp
include/ores.COMPONENT.PART/domain/stub.hpp  
src/domain/stub.cpp  
tests/main.cpp
tests/stub_tests.cpp
include/ores.COMPONENT.service/app/application*.hpp (×3)    
include/ores.COMPONENT.service/config/*.hpp (×3)    
src/app/application.cpp, src/app/host.cpp    
src/config/options.cpp, src/config/parser.cpp    
src/main.cpp    

The generated src/CMakeLists.txt deps per profile:

Profile PUBLIC deps PRIVATE deps
component-api ores.eventing.lib, ores.platform.lib ores.utility.lib, faker-cxx, libfort
component-core ores.COMPONENT.api.lib, ores.nats.lib ores.service.lib, ores.platform.lib, ores.utility.lib, ores.security.lib, faker-cxx, libfort
component-service ores.service.lib, ores.security.lib, ores.COMPONENT.core.lib, ores.eventing.lib, ores.nats.lib, ores.database.lib, ores.utility.lib, ores.telemetry.lib  

After generation, adjust the target_link_libraries in src/CMakeLists.txt to match the actual dependencies of your component.

Step 4: Register in projects/CMakeLists.txt

Add each part to projects/CMakeLists.txt in dependency order (.api before .core before .service), inserted after their nearest dependency:

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ores.refdata)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ores.COMPONENT.api)   # new
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ores.COMPONENT.core)  # new
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ores.COMPONENT.service)  # new (if applicable)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ores.assets)

Step 5: Add PlantUML diagram stub

The code generator does not yet produce the PlantUML diagram content. Manually create one .puml file per part, e.g. projects/ores.COMPONENT.api/modeling/ores.COMPONENT.api.puml:

' -*- mode: plantuml; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
'
' Copyright (C) 2026 Marco Craveiro <marco.craveiro@gmail.com>
'
' This program is free software; you can redistribute it and/or modify it under
' the terms of the GNU General Public License as published by the Free Software
' Foundation; either version 3 of the License, or (at your option) any later
' version.
'
' This program is distributed in the hope that it will be useful, but WITHOUT
' ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
' FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License along with
' this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
' Street, Fifth Floor, Boston, MA 02110-1301, USA.
'
@startuml

title ores.COMPONENT Component

set namespaceSeparator ::

namespace ores #F2F2F2 {
    namespace COMPONENT #F2F2F2 {
        ' Domain types to be added.
    }
}

@enduml

Step 6: Build and test

Using the CMake Runner Skill:

  1. Build and run the tests for each part:

    cmake --build --preset linux-clang-debug-ninja --target ores.COMPONENT.api.tests
    cmake --build --preset linux-clang-debug-ninja --target ores.COMPONENT.core.tests
    cmake --build --preset linux-clang-debug-ninja --target ores.COMPONENT.service.tests
    
  2. Confirm the stub test passes for each part.
  3. Commit all your changes:

    [analytics] Add ores.COMPONENT.{api,core,service} component scaffolds
    

Reference: Component structure

Component parts

Standard components are made up of the following well-known parts (directories):

Part name Description
include Contains the C++ header files.
modeling Contains the PlantUML source and PNG for diagrams.
src Contains the C++ implementation files.
tests Contains the Catch2 tests for the component.

Facets

Within include and src, code is organised into facets:

Facet name Description
domain C++ domain types (POCOs) and associated services (JSON, table I/O, etc.)
generators C++ generators for domain types, used in testing and production.
messaging Network messaging: requests, responses, handlers, protocol types.
repository Database support via sqlgen: repositories, entities, mappers.
eventing Event-related classes.
service Standalone types with domain operations that do not fit into a domain type.
app Executable infrastructure: hosting, startup, etc.
config Top-level configuration; command-line parser for executable components.
net Network utilities: client/server infrastructure, network interface info.
orexml ORE (Open Source Risk Engine) import/export support.
csv CSV import/export support.

CMake dependency visibility

When customising src/CMakeLists.txt dependencies, use the correct visibility:

  • PUBLIC: dependency headers exposed in component's public headers; consumers also link this dependency.
  • PRIVATE: dependency only used in .cpp files; consumers do not see it.
  • INTERFACE: expose a dependency to consumers without linking it directly (use to avoid duplicate library warnings on macOS).

Common transitive dependencies (do not add these explicitly):

  • reflectcpp comes from ores.platform.lib (PUBLIC via ores.utility.lib)
  • Boost::program_options comes from ores.telemetry.lib (PUBLIC)

Component model documentation

Once the scaffold is working, document the component's architecture using the Component Model Creator skill. This produces:

  • modeling/ores.COMPONENT.org — Component architecture documentation
  • modeling/ores.COMPONENT.puml — Refined class diagram
  • modeling/ores.COMPONENT.png — Generated diagram image

Emacs 29.1 (Org mode 9.6.6)