vix modules
vix modules organizes application code into clean, explicit C++ modules.
Use it when your Vix app starts growing and you want to split code by feature, domain, or responsibility without turning the whole project into a complex CMake setup.
vix modules init
vix modules add auth2
Overview
vix modules adds an app-first module organization layer to Vix projects.
It works with:
vix.app projects
CMake projects2
The modern recommended path for simple applications is:
vix.app
modules = [...]2
CMake still works and remains the advanced compatibility path.
The goal is simple:
small app
clear modules
explicit dependencies
no manual CMake for common cases
CMake available when needed2
3
4
5
The important idea
For Vix apps, modules are declared in vix.app.
Example:
name = api
type = executable
standard = c++20
sources = [
src/main.cpp,
]
include_dirs = [
src,
]
modules = [
auth,
users,
orders,
]
packages = [
vix,
]
links = [
vix::vix,
]
output_dir = bin2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
This tells Vix:
this app uses modules/auth
this app uses modules/users
this app uses modules/orders2
3
When Vix builds a vix.app project, it generates an internal CMake project under:
.vix/generated/app/CMakeLists.txtThat generated CMake project loads your modules automatically.
You do not edit the generated file.
You edit:
vix.appCMake still works
If your project already has:
CMakeLists.txtVix uses it.
Project resolution order:
1. CMakeLists.txt
2. vix.app2
That means:
If CMakeLists.txt exists, Vix uses CMakeLists.txt.
If CMakeLists.txt does not exist but vix.app exists, Vix uses vix.app.2
So this project uses CMake:
api/
CMakeLists.txt
vix.app
modules/
src/2
3
4
5
This project uses vix.app:
api/
vix.app
modules/
src/2
3
4
This keeps existing CMake projects compatible while allowing new Vix apps to stay simpler.
When to use modules
Use modules when your app has separate areas like:
auth
users
orders
billing
notifications
catalog
storage
search2
3
4
5
6
7
8
Instead of putting everything in:
src/you can use:
modules/
auth/
users/
orders/2
3
4
Each module has its own public API, private implementation, and build target.
What a module is
A Vix module is a small C++ library inside your application.
A module named auth looks like this:
modules/auth/
├── CMakeLists.txt
├── include/
│ └── auth/
│ └── api.hpp
└── src/
└── auth.cpp2
3
4
5
6
7
The public header is:
modules/auth/include/auth/api.hppThe private implementation is:
modules/auth/src/auth.cppThe module target is:
<project>_authThe public alias target is:
<project>::authFor a project named api, the alias is:
api::authBasic workflow with vix.app
Create an app:
vix new api --app
cd api2
Initialize modules:
vix modules initAdd modules:
vix modules add auth
vix modules add users2
Declare them in vix.app:
modules = [
auth,
users,
]2
3
4
Use them in code:
#include <auth/api.hpp>
#include <users/api.hpp>2
Build:
vix buildRun:
vix runBasic workflow with CMake
For an existing CMake project:
vix modules init
vix modules add auth
vix build2
3
In CMake projects, vix modules init can patch the root CMakeLists.txt with:
# VIX_MODULES_BEGIN
include(${CMAKE_CURRENT_LIST_DIR}/cmake/vix_modules.cmake)
# VIX_MODULES_END2
3
When a module is added, Vix can also add a guarded link block to connect the module to the main target.
This keeps existing CMake projects working.
Why vix.app does not patch CMakeLists.txt
A vix.app project usually has no root CMakeLists.txt.
That is intentional.
When you run:
vix modules initinside a vix.app project, Vix creates:
modules/
cmake/vix_modules.cmake2
but skips patching CMakeLists.txt because the app is controlled by vix.app.
You should connect modules through:
modules = [
auth,
users,
]2
3
4
not by editing generated CMake.
Generated files
vix modules init creates:
modules/
cmake/vix_modules.cmake2
vix modules add auth creates:
modules/auth/
├── CMakeLists.txt
├── include/
│ └── auth/
│ └── api.hpp
└── src/
└── auth.cpp2
3
4
5
6
7
The generated module is ready to build.
vix.app modules field
The modules field is for internal app modules.
Example:
modules = [
auth,
users,
billing,
]2
3
4
5
These names map to module folders:
modules/auth
modules/users
modules/billing2
3
And to CMake alias targets:
api::auth
api::users
api::billing2
3
Do not use modules for registry packages.
Use deps for registry packages.
modules vs deps
Use modules for code inside your app.
Use deps for packages from the Vix Registry.
Example:
modules = [
auth,
users,
]
deps = [
gk/json@^1.0.0,
]2
3
4
5
6
7
8
The difference is important:
| Field | Purpose | Example |
|---|---|---|
modules | Internal app modules under modules/ | auth |
deps | External packages from the Vix Registry | gk/json@^1.0.0 |
packages | CMake packages resolved with find_package | vix |
links | CMake targets linked to the app | vix::vix |
Full vix.app example with modules
name = api
type = executable
standard = c++20
sources = [
src/main.cpp,
]
include_dirs = [
src,
]
modules = [
auth,
users,
orders,
]
deps = [
]
packages = [
vix,
]
links = [
vix::vix,
]
resources = [
.env=.env,
]
output_dir = bin2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
This is the app-first Vix structure.
The app owns the modules.
The modules stay clean and explicit.
Full project structure
A modular vix.app project can look like this:
api/
├── vix.app
├── vix.json
├── .env
├── .env.example
├── src/
│ └── main.cpp
├── modules/
│ ├── auth/
│ │ ├── CMakeLists.txt
│ │ ├── include/
│ │ │ └── auth/
│ │ │ └── api.hpp
│ │ └── src/
│ │ └── auth.cpp
│ ├── users/
│ │ ├── CMakeLists.txt
│ │ ├── include/
│ │ │ └── users/
│ │ │ └── api.hpp
│ │ └── src/
│ │ └── users.cpp
│ └── orders/
│ ├── CMakeLists.txt
│ ├── include/
│ │ └── orders/
│ │ └── api.hpp
│ └── src/
│ └── orders.cpp
└── cmake/
└── vix_modules.cmake2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Public include style
Use public include paths:
#include <auth/api.hpp>
#include <users/api.hpp>2
Do not use relative module paths:
#include "../modules/auth/include/auth/api.hpp"The module target exposes its public include directory.
The include should stay clean.
Generated module header
A generated module header can look like this:
#ifndef api_auth_api_hpp
#define api_auth_api_hpp
#include <string>
namespace api::auth
{
struct Api
{
static std::string name();
};
}
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
The exact namespace depends on the project name and module name.
Generated module implementation
A generated module implementation can look like this:
#include <auth/api.hpp>
namespace api::auth
{
std::string Api::name()
{
return "api::auth";
}
}2
3
4
5
6
7
8
9
Generated module CMake target
A generated module CMake file creates a real target and an alias target.
Example for project api and module auth:
add_library(api_auth)
add_library(api::auth ALIAS api_auth)
target_sources(api_auth
PRIVATE
src/auth.cpp
)
target_include_directories(api_auth
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/include
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/src
)
target_compile_features(api_auth PUBLIC cxx_std_20)
set_target_properties(api_auth PROPERTIES
OUTPUT_NAME "api_auth"
)2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
The alias target is the public name:
api::authModule loader
vix modules init creates:
cmake/vix_modules.cmakeThe loader scans:
modules/and adds every module that contains:
CMakeLists.txtConceptually:
file(GLOB VIX_MODULE_DIRS RELATIVE "${VIX_MODULES_DIR}" "${VIX_MODULES_DIR}/*")
foreach(_m ${VIX_MODULE_DIRS})
if(IS_DIRECTORY "${VIX_MODULES_DIR}/${_m}")
if(EXISTS "${VIX_MODULES_DIR}/${_m}/CMakeLists.txt")
add_subdirectory("${VIX_MODULES_DIR}/${_m}" "${CMAKE_BINARY_DIR}/vix_modules/${_m}")
endif()
endif()
endforeach()2
3
4
5
6
7
8
9
This loader is used by both paths:
vix.app generated CMake
manual CMake project2
How vix.app connects modules internally
For a vix.app project, Vix generates internal CMake.
The generated project can include the module loader and link declared modules.
Conceptually:
vix.app
-> reads modules = [...]
-> generates .vix/generated/app/CMakeLists.txt
-> includes cmake/vix_modules.cmake
-> links module aliases to the app target2
3
4
5
So this:
modules = [
auth,
users,
]2
3
4
maps to:
api::auth
api::users2
and links them into the app.
Do not edit generated CMake
Do not edit:
.vix/generated/app/CMakeLists.txtIt is generated by Vix.
If you need to add a module, edit:
modules = [
auth,
users,
orders,
]2
3
4
5
If you need to add a registry dependency, edit or use vix add so the project metadata and lockfile stay aligned.
If you need full custom build logic, use a real CMakeLists.txt.
Adding a module
Run:
vix modules add authThis creates:
modules/auth/include/auth/api.hpp
modules/auth/src/auth.cpp
modules/auth/CMakeLists.txt2
3
Then add it to vix.app:
modules = [
auth,
]2
3
Build:
vix buildAdding multiple modules
vix modules add auth
vix modules add users
vix modules add orders2
3
Then:
modules = [
auth,
users,
orders,
]2
3
4
5
Use in code:
#include <auth/api.hpp>
#include <users/api.hpp>
#include <orders/api.hpp>2
3
Module naming rules
Module names may contain:
letters
numbers
_
-2
3
4
Examples:
auth
users
order_items
payment-gateway2
3
4
Hyphens are normalized to underscores for target names.
Example:
payment-gatewaybecomes:
payment_gatewaySo the alias for project api becomes:
api::payment_gatewayReserved module names
Avoid names that conflict with project structure, build tools, or common dependency names.
Examples of reserved or bad names:
modules
module
src
include
cmake
build
test
tests
example
examples
vendor
third_party
internal
private
public
main
app
api
core
std
vix
vixcpp
registry
deps
fmt
boost
openssl
sqlite
mysql
asio
beast2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Use domain names instead:
auth
users
orders
billing
notifications
inventory
search2
3
4
5
6
7
--project
Use --project to set the project name used for module targets.
vix modules add auth --project apiThis creates aliases like:
api::authUse this when Vix cannot detect the project name correctly.
--dir
Use --dir to run module commands from another directory.
vix modules init --dir ./apps/api
vix modules add auth --dir ./apps/api
vix modules check --dir ./apps/api2
3
Equivalent form:
vix modules add auth --dir=./apps/api--no-patch
Use --no-patch with init when you do not want Vix to patch a root CMakeLists.txt.
vix modules init --no-patchThis still creates:
modules/
cmake/vix_modules.cmake2
but does not modify root CMake.
For vix.app projects, root CMake patching is skipped because vix.app is the source of truth.
--patch
Use --patch to explicitly allow root CMake patching.
vix modules init --patchThis matters only for CMake projects with a root CMakeLists.txt.
--no-link
Use --no-link when adding a module if you do not want Vix to patch the root CMake link block.
vix modules add auth --no-linkFor vix.app projects, prefer declaring the module in vix.app:
modules = [
auth,
]2
3
For manual CMake projects, link manually:
target_link_libraries(api PRIVATE api::auth)--link
Use --link to allow Vix to patch a CMake project link block.
vix modules add auth --linkThis is useful for classic CMake projects.
For vix.app, linking is controlled by:
modules = [...]Cross-module dependencies
If one module uses another module, the dependency must be explicit.
Example:
#include <auth/api.hpp>If users includes auth, then users must link to auth.
In:
modules/users/CMakeLists.txtadd:
target_link_libraries(api_users PUBLIC api::auth)or:
target_link_libraries(api_users PRIVATE api::auth)The correct visibility depends on where the dependency is used.
PUBLIC vs PRIVATE dependencies
Use PUBLIC when the dependency appears in a public header.
Example:
// modules/users/include/users/api.hpp
#include <auth/api.hpp>2
Then:
target_link_libraries(api_users PUBLIC api::auth)Use PRIVATE when the dependency is only used inside .cpp files.
Example:
// modules/users/src/users.cpp
#include <auth/api.hpp>2
Then:
target_link_libraries(api_users PRIVATE api::auth)Module safety rules
Run:
vix modules checkThis checks module structure and dependency safety.
The main rules are:
public headers must not include private implementation files
cross-module includes must be declared through target_link_libraries
module dependencies must be explicit2
3
Public headers must not include private files
Wrong:
#include "../src/auth_impl.hpp"or:
#include <auth/src/auth_impl.hpp>Public headers should expose stable public API only.
Correct:
#include <auth/api.hpp>Private implementation headers should stay under:
modules/auth/src/and be included only by implementation files.
Cross-module includes must be declared
If a module includes another module:
#include <auth/api.hpp>the CMake dependency must exist.
Example:
target_link_libraries(api_users PUBLIC api::auth)This makes the dependency visible to the build system.
It also avoids hidden include path problems.
App code using modules
In your app source:
#include <vix.hpp>
#include <auth/api.hpp>
#include <users/api.hpp>
using namespace vix;
int main()
{
App app;
app.get("/", [](Request &, Response &res) {
res.json({
"ok", true,
"auth", api::auth::Api::name(),
"users", api::users::Api::name()
});
});
app.run();
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Your vix.app must include:
modules = [
auth,
users,
]2
3
4
App-first architecture example
A real backend can evolve like this:
api/
├── vix.app
├── src/
│ └── main.cpp
├── modules/
│ ├── auth/
│ ├── users/
│ ├── orders/
│ ├── billing/
│ └── notifications/
└── cmake/
└── vix_modules.cmake2
3
4
5
6
7
8
9
10
11
12
Each module owns one part of the domain.
Example responsibilities:
| Module | Responsibility |
|---|---|
auth | login, tokens, permissions |
users | user profile and user lookup |
orders | order creation and order state |
billing | payments, invoices, subscriptions |
notifications | email, websocket, push events |
Recommended module boundaries
A module should own one clear responsibility.
Good module names:
auth
users
orders
billing
notifications
catalog
inventory
search
files
storage2
3
4
5
6
7
8
9
10
Avoid generic names:
utils
helpers
core
common
misc2
3
4
5
Generic modules become dumping grounds.
Prefer domain modules.
Keep main.cpp small
Do not put every route and service directly in main.cpp.
Prefer:
#include <vix.hpp>
#include <auth/api.hpp>
#include <users/api.hpp>
using namespace vix;
static void register_routes(App &app)
{
app.get("/", [](Request &, Response &res) {
res.text("ok");
});
}
int main()
{
App app;
register_routes(app);
app.run();
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
As the app grows, modules should own their own route registration functions.
Example:
auth::register_routes(app);
users::register_routes(app);2
Module route registration pattern
A module can expose a route registration API.
Example:
// modules/auth/include/auth/api.hpp
#ifndef api_auth_api_hpp
#define api_auth_api_hpp
#include <vix.hpp>
namespace api::auth
{
void register_routes(vix::App &app);
}
#endif2
3
4
5
6
7
8
9
10
11
12
Implementation:
// modules/auth/src/auth.cpp
#include <auth/api.hpp>
namespace api::auth
{
void register_routes(vix::App &app)
{
app.get("/auth/health", [](vix::Request &, vix::Response &res) {
res.json({
"ok", true,
"module", "auth"
});
});
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
App:
#include <vix.hpp>
#include <auth/api.hpp>
int main()
{
vix::App app;
api::auth::register_routes(app);
app.run();
return 0;
}2
3
4
5
6
7
8
9
10
11
12
Module service pattern
A module can expose application services.
Example:
// modules/users/include/users/api.hpp
#ifndef api_users_api_hpp
#define api_users_api_hpp
#include <string>
namespace api::users
{
struct UserService
{
std::string find_name_by_id(int id) const;
};
}
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
Implementation:
// modules/users/src/users.cpp
#include <users/api.hpp>
namespace api::users
{
std::string UserService::find_name_by_id(int id) const
{
return "user-" + std::to_string(id);
}
}2
3
4
5
6
7
8
9
10
Modules and registry dependencies
Modules can use registry dependencies, but registry dependencies belong to the app dependency model.
Example:
deps = [
gk/json@^1.0.0,
]
links = [
vix::vix,
gk::json,
]2
3
4
5
6
7
8
Then a module can link to the dependency in its own CMakeLists.txt if needed.
Example:
target_link_libraries(api_users PRIVATE gk::json)Keep the rule:
vix.app declares app-level packages and registry deps
module CMake declares module-level target dependencies2
When to move to manual CMake
Stay with vix.app when your app has:
one main target
simple modules
normal packages
normal links
normal resources2
3
4
5
Move to CMakeLists.txt when you need:
multiple custom targets
custom commands
generated sources
install rules
CTest integration
complex platform-specific logic
advanced package exports
custom toolchains
deep CMake functions2
3
4
5
6
7
8
9
Adding a CMakeLists.txt is enough.
Vix will automatically use CMake because CMake has priority.
Commands
| Command | Purpose |
|---|---|
vix modules init | Initialize module support. |
vix modules add <name> | Create a new module. |
vix modules check | Validate module rules. |
vix modules --help | Show help. |
Options
| Option | Description |
|---|---|
-d, --dir <path> | Project directory. |
--dir=<path> | Same as --dir <path>. |
--project <name> | Project name used for generated module targets. |
--project=<name> | Same as --project <name>. |
--no-patch | Do not patch root CMakeLists.txt during init. |
--patch | Allow root CMakeLists.txt patching during init. |
--no-link | Do not patch root CMake link block during add. |
--link | Allow root CMake link patching during add. |
-h, --help | Show help. |
Common workflows
Start modules in a vix.app project
vix modules init
vix modules add auth
vix modules add users2
3
Then edit vix.app:
modules = [
auth,
users,
]2
3
4
Build:
vix buildStart modules in a CMake project
vix modules init
vix modules add auth
vix build2
3
If needed, link manually:
target_link_libraries(api PRIVATE api::auth)Add a module without CMake auto-link patch
vix modules add auth --no-linkThen either add it to vix.app:
modules = [
auth,
]2
3
or link manually in CMake:
target_link_libraries(api PRIVATE api::auth)Check module rules
vix modules checkRun from another directory
vix modules add auth --dir ./apps/apiForce project name
vix modules add auth --project apiCommon mistakes
Forgetting to add the module to vix.app
Wrong:
vix modules add auth
vix build2
without updating:
modules = [
auth,
]2
3
Correct:
vix modules add authThen:
modules = [
auth,
]2
3
Editing generated CMake
Wrong:
.vix/generated/app/CMakeLists.txtCorrect:
vix.appFor simple apps, edit vix.app.
For advanced apps, create a real CMakeLists.txt.
Using modules for registry packages
Wrong:
modules = [
gk/json@^1.0.0,
]2
3
Correct:
deps = [
gk/json@^1.0.0,
]2
3
Forgetting cross-module CMake dependencies
Wrong:
#include <auth/api.hpp>inside users, but no link in modules/users/CMakeLists.txt.
Correct:
target_link_libraries(api_users PUBLIC api::auth)or:
target_link_libraries(api_users PRIVATE api::auth)Using relative includes
Wrong:
#include "../modules/auth/include/auth/api.hpp"Correct:
#include <auth/api.hpp>Creating generic dumping-ground modules
Avoid:
utils
helpers
common
misc2
3
4
Prefer domain modules:
auth
users
orders
billing
notifications2
3
4
5
Expecting vix.app to be used when CMakeLists.txt exists
If your project has:
CMakeLists.txt
vix.app2
Vix uses:
CMakeLists.txtIf you want to test vix.app, temporarily rename CMakeLists.txt.
Troubleshooting
modules/ folder not found
Run:
vix modules initThen:
vix modules add authModule already exists
The folder already exists:
modules/authChoose another name or remove the existing module intentionally.
Invalid module name
Use only:
letters
numbers
_
-2
3
4
Good:
vix modules add auth
vix modules add user_profiles
vix modules add payment-gateway2
3
Bad:
vix modules add "user profiles"
vix modules add auth/core2
Reserved module name
Choose a domain name instead of a tool, folder, or framework name.
Good:
billing
orders
files
notifications2
3
4
Bad:
src
include
vix
core
sqlite
boost2
3
4
5
6
Module compiles but app cannot include header
Make sure the module is declared in vix.app:
modules = [
auth,
]2
3
For CMake projects, make sure the app links the module:
target_link_libraries(api PRIVATE api::auth)Module includes another module but build fails
Add the module dependency:
target_link_libraries(api_users PRIVATE api::auth)Use PUBLIC if the dependency appears in public headers.
vix.app project says CMake patch skipped
That is expected.
For vix.app, add modules in:
modules = [
auth,
]2
3
Root CMake patching is only for CMake projects.
Best practices
Use vix.app for simple application modules.
Use modules = [...] as the source of truth in app-first projects.
Use CMake only when you need advanced build control.
Keep module names domain-focused.
Expose public headers under:
modules/<name>/include/<name>/Keep private implementation under:
modules/<name>/src/Use angle-bracket includes:
#include <auth/api.hpp>Declare cross-module dependencies explicitly with target_link_libraries.
Use PUBLIC only when the dependency appears in public headers.
Use PRIVATE when the dependency is only used in implementation files.
Run:
vix modules checkbefore committing larger module changes.
Do not edit generated CMake under .vix/generated/app.
Related commands
| Command | Purpose |
|---|---|
vix build | Build the app and its modules. |
vix run | Run the modular app. |
vix dev | Rebuild and restart during development. |
vix check | Validate project health. |
vix tests | Run tests. |
vix add | Add registry dependencies. |
vix install | Install project dependencies. |
Next step
Learn how vix.app resolves projects and falls back to CMake.