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.liblinks:ores.eventing.lib,ores.platform.lib(PUBLIC)ores.COMPONENT.core.liblinks:ores.COMPONENT.api.lib,ores.database.lib,sqlgen(PRIVATE)ores.COMPONENT.servicelinks: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.
- Gather information about the new component (name, purpose, etc).
- Decide which parts are needed (
.api,.core,.service, or a subset). - Create one component model JSON file per part.
- Run the code generator with the
componentprofile for each part. - Register each part in
projects/CMakeLists.txt. - Add the PlantUML diagram stub for each part.
- 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.,
tradingforores.trading.*). - Parts needed: which of
.api,.core,.serviceare 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:
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
- Confirm the stub test passes for each part.
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
.cppfiles; 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):
reflectcppcomes fromores.platform.lib(PUBLIC viaores.utility.lib)Boost::program_optionscomes fromores.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 documentationmodeling/ores.COMPONENT.puml— Refined class diagrammodeling/ores.COMPONENT.png— Generated diagram image