Vix.cpp v2.7.1
Vix.cpp v2.7.1 introduces the first complete foundation for Vix App Modules.
Applications and backend projects can now declare internal modules in vix.app, enable or disable them from one place, generate module-specific source structures, wire enabled modules into the executable automatically, and validate architectural problems before they become build failures.
The release also updates vix dev so changes to vix.app trigger the configuration work required to regenerate module wiring. SDK lifecycle handling and vix uninstall receive a broader command workflow for inspecting and removing CLI installations, SDK profiles, and globally installed packages.
Release focus
A small C++ application can remain understandable with one executable target and a compact src/ directory. As the project grows, that structure often becomes less clear.
Authentication, projects, package management, storage, billing, build history, administration, and other areas begin to share the same source tree. Routes are registered from several places, tests lose their connection to the feature they cover, and disabling one part of the application may require manual edits across CMake, startup code, and source files.
Vix App Modules provide an internal organization layer for this kind of project.
A module belongs to one application. It can contain its own source files, routes, controller, tests, migrations, and metadata, while the application keeps one executable, one dependency graph, and one main runtime.
This is different from creating an independent library for every feature. Internal modules are intended to organize one application without forcing each feature to become a separately versioned or installed package.
Declaring modules in vix.app
Application modules are declared through [module.<name>] sections in vix.app.
A basic declaration looks like this:
[module.auth]
enabled = true
path = "modules/auth"
kind = "backend"
depends = []The module name comes from the section name. The remaining fields describe how the application should load it.
enabled determines whether the module participates in the active build.
path points to the module directory relative to the project root.
kind describes the role of the module in the application workflow.
depends records dependencies between internal application modules.
For example:
[module.projects]
enabled = true
path = "modules/projects"
kind = "backend"
depends = ["auth"]This states that projects is active and requires the auth module.
The declaration is part of the application manifest because module activation is an application-level decision. A module directory may exist on disk without participating in every build.
Application manifest support
The vix.app loader now parses module declarations into structured application metadata.
Each module is represented with its:
name
enabled state
path
kind
internal dependenciesThis metadata is used consistently by module listing, validation, generated CMake, runtime wiring, dev-mode rebuild decisions, and CLI module commands.
The application manifest also supports:
type = "backend"A backend application is mapped internally to an executable target. This gives backend projects the same module-aware generated build path as other executable vix.app applications.
Creating an application module
A module can be created with:
vix modules add authInside a vix.app project, the command now performs more than creating a folder.
It generates the module structure, writes a vix.module manifest, creates a test file, and registers the new module in the root vix.app.
The developer does not need to add the [module.auth] section manually after generation.
The exact generated structure depends on the application type. Backend projects receive a backend-oriented module, while general application projects receive a routed service module.
Backend module generation
Inside a backend project, vix modules add generates a module prepared for routes, controllers, migrations, tests, and future data or service layers.
A generated module contains files such as:
modules/auth/
├── CMakeLists.txt
├── vix.module
├── include/
│ ├── AuthModule.hpp
│ └── AuthController.hpp
├── src/
│ ├── AuthModule.cpp
│ └── AuthController.cpp
├── migrations/
└── tests/
└── test_auth.cppThe generated controller and module provide a small working route rather than an empty placeholder.
This allows the module to compile, register itself, and demonstrate the expected application integration immediately after creation.
The initial skeleton remains deliberately small. It creates the boundaries required by the workflow without deciding that every backend module must use a particular repository, service, model, or persistence architecture.
Those layers can be added when the module actually needs them.
Service modules for application projects
General executable app projects receive routed service modules.
A generated service module contains:
<Module>Module.hpp
<Module>Module.cpp
<Module>Controller.hpp
<Module>Controller.cpp
vix.module
tests/test_<module>.cppThe generated example includes route registration and a minimal HTTP response so the developer can verify that the module is active.
Service modules are recorded with:
kind = "service"This allows generated application wiring to distinguish them from unrelated source folders and include them in route registration.
The module remains part of the main application runtime. It does not create a separate server process or executable.
Module manifests
Every generated module receives a vix.module file.
The manifest describes the module itself rather than its application-level activation state.
A basic generated manifest can contain:
name = "auth"
kind = "backend"
[routes]
prefix = "/api/auth"
[tests]
enabled = trueThe root vix.app decides whether the module is enabled and where it lives. The module manifest describes details that belong to the module, such as its kind, route prefix, and test configuration.
This separation allows module metadata to stay close to the module source while keeping the active application composition visible from one root file.
Enabling and disabling modules
Declared modules can be activated through the CLI:
vix modules enable authThey can be disabled with:
vix modules disable authThese commands update the corresponding enabled value in vix.app.
A disabled module can remain in the repository without being compiled or linked. Its files, tests, and manifest stay available for later use, but it does not participate in the current application.
This is useful for optional features, experimental work, deployment variants, and modules that are temporarily unavailable while another part of the project is being changed.
Disabling a module is not implemented by deleting its CMake files or commenting out startup code. The application manifest remains the source of truth.
Listing application modules
The active module state can be inspected with:
vix modules listThe output includes the declared module name, enabled state, kind, configured path, filesystem status, and internal dependencies.
This helps distinguish several conditions that would otherwise look similar during a build:
- a module is declared and enabled;
- a module is declared but disabled;
- a module is declared but missing on disk;
- a directory exists but is not declared;
- a module depends on another module.
The command reflects vix.app, not every arbitrary folder found under modules/.
Enabled-module build generation
Generated vix.app CMake projects now load only the modules enabled in the application manifest.
Vix emits the active set through:
VIX_ENABLED_MODULESThis list controls which module directories are added to the generated build.
An empty list is emitted explicitly when no modules are enabled. This is important because the absence of the variable could otherwise cause the older CMake fallback to load every directory under modules/.
The behavior now differs intentionally between project types:
vix.app project:
load only VIX_ENABLED_MODULES
classic CMake project:
preserve legacy modules/* discoveryClassic projects continue to use the previous convention unless they adopt the vix.app module workflow.
Automatic application wiring
Enabled modules are connected to executable applications through generated source files:
.vix/generated/app/include/vix_app_modules.hpp
.vix/generated/app/vix_app_modules.cppThe generated implementation includes the enabled routed modules and provides the registration code used by the application startup path.
For executable vix.app targets, vix_app_modules.cpp is added automatically to the generated CMake target.
The application template keeps a small integration point rather than requiring developers to modify src/main.cpp whenever a module is added or disabled.
This allows the root application bootstrap to remain stable while module registration follows the manifest.
Module registry integration
Generated app projects now include a small module registry layer:
include/app/ModuleRegistry.hpp
src/app/ModuleRegistry.cppThe registry provides a clear point where generated module registration and application startup meet.
The goal is not to hide module construction behind a large runtime framework. It is to prevent the main source file from becoming a manually maintained list of every route and feature in the application.
A typical application entry point can initialize its core runtime and delegate module registration to the registry.
When the module set changes, Vix regenerates the application module wiring without requiring the developer to rewrite the main bootstrap.
Route registration
Enabled routed modules register their routes automatically.
For a module with:
[routes]
prefix = "/api/auth"the generated application wiring includes the module registration hook associated with that route group.
When the module is disabled, its generated registration disappears from the active build. The route is no longer available because the module itself is not compiled or wired into the executable.
This behavior was validated for both service modules in app projects and backend modules in backend projects.
Route availability therefore follows the same activation state as compilation and linking.
Internal module dependencies
Modules can declare dependencies on other modules:
[module.projects]
enabled = true
path = "modules/projects"
kind = "backend"
depends = ["auth"]Internal dependencies describe application structure rather than registry packages.
The declaration says that the projects module expects the auth module to participate in the same application.
Vix validates these relationships before the generated build is configured.
An enabled module cannot depend on an undeclared module, and it cannot depend on a module that is currently disabled.
This prevents application configurations where compilation succeeds partially but required runtime behavior is absent.
Circular dependency detection
vix modules check now detects circular internal dependencies.
For example:
auth depends on projects
projects depends on authThis structure is rejected before CMake generation.
Circular module relationships usually indicate that the boundary between two features is unclear or that shared behavior should move into a lower-level module.
Detecting the cycle at the manifest level gives the developer a direct architectural error rather than allowing the relationship to emerge later through include paths, link order, or runtime initialization.
Module validation
The module checker now validates the complete relationship between vix.app, the filesystem, module manifests, and internal dependencies.
Run:
vix modules checkThe command reports conditions such as:
declared module missing on disk
enabled module missing CMakeLists.txt
enabled module missing vix.module
module directory not declared in vix.app
dependency on an undeclared module
dependency on a disabled module
circular module dependency
duplicate route prefixThese checks are intended to catch architectural drift early.
Without them, a module may appear in the source tree but never compile, two modules may register the same route prefix, or a disabled dependency may leave another feature in an invalid state.
Duplicate route prefixes
Vix now checks route prefixes declared in enabled module manifests.
Two modules declaring the same prefix can create ambiguous or order-dependent route behavior.
For example:
# modules/auth/vix.module
[routes]
prefix = "/api/users"and:
# modules/accounts/vix.module
[routes]
prefix = "/api/users"will produce a module validation error.
The check happens before runtime registration, where the resulting behavior would be harder to understand.
Generated module tests
New modules include a test file by default.
Generated CMake creates module test targets when the application test option is enabled:
<app>_BUILD_TESTSThe generated application CMake now declares its test options before module directories are loaded.
This ordering is important because modules decide whether to create their test targets while their CMake files are being evaluated.
Previously, the application test option could be introduced after the modules had already been processed, causing valid module tests to be skipped.
Module tests can now be discovered and run through:
vix testsThe generated test provides a starting point and confirms that the module target participates correctly in the application build.
Dev mode and manifest changes
vix dev now treats vix.app as an active project configuration file.
A source or header change can continue through the fast rebuild path. The existing generated CMake structure remains valid, so Vix rebuilds and restarts the application without repeating unnecessary project generation.
A change to vix.app is different.
Enabling a module, disabling a module, changing a module path, or editing the application target can alter generated CMake and module wiring.
Vix now recognizes this distinction:
source or header change:
fast rebuild
vix.app change:
regenerate, reconfigure, rebuild, restartThis makes dev mode follow the real project state rather than continuing to run an executable generated from an older manifest.
Manifest-aware regeneration
When vix.app changes, vix dev can regenerate:
generated application CMake
VIX_ENABLED_MODULES
vix_app_modules.hpp
vix_app_modules.cpp
module registration
target source listsThe project is then reconfigured before rebuilding.
This fixes cases where editing the module list appeared to have no effect during watch mode because the previous fast rebuild path did not revisit application generation.
The developer can now enable or disable a module while vix dev is active and receive an application built from the updated manifest.
SDK lifecycle improvements
This release also improves how installed SDK profiles are registered and removed.
SDK upgrades now register installed profiles with the CMake user package registry.
This helps CMake-based consumer projects locate the installed SDK through the expected package discovery mechanisms.
The uninstall workflow removes the related SDK state rather than deleting only the main installation directory.
Cleanup can include:
installed SDK directory
current profile metadata
current profile pointer
CMake user package registry entryThis prevents a removed SDK from continuing to appear active through stale metadata or CMake registration.
Expanded uninstall workflow
vix uninstall now provides a command experience aligned with the newer vix upgrade workflow.
Normal output uses clearer sections, status lines, hints, and completion messages.
A removal can be inspected before files are deleted with:
vix uninstall --dry-runMachine-readable output is available through:
vix uninstall --jsonDetailed diagnostic output can be requested with:
vix uninstall --verboseThe command now covers CLI removal, SDK profiles, and globally installed packages through one consistent interface.
SDK uninstall commands
Installed SDK profiles can be managed with:
vix uninstall --sdk <profile>
vix uninstall --sdk-all
vix uninstall --sdk-list--sdk-list shows the installed profiles available for removal.
--sdk <profile> removes one selected profile and its associated metadata.
--sdk-all removes all installed SDK profiles.
These commands do not uninstall the Vix CLI unless the user explicitly selects the broader CLI removal workflow.
This separation is useful when changing SDK profiles while keeping the command-line tool itself installed.
Global package uninstall
Globally installed packages can be removed with:
vix uninstall -g <package>or:
vix uninstall --global <package>The package entry is removed from the global installation manifest together with the files owned by that package.
This fixes cases where the files were removed but the global package registry continued to report the package as installed.
The command also uses the newer uninstall output rather than a separate older presentation path.
CLI uninstall path detection
Removing the Vix CLI safely requires identifying the actual binary being used.
The command can now resolve the installation path from several sources:
installation metadata
VIX_CLI_PATH
shell command lookup
explicit installation prefix
explicit binary pathExplicit options include:
--prefix <dir>
--path <file>
--systemThis avoids assuming that every installation lives under one fixed system directory.
A user-built CLI, a system installation, and a custom-prefix installation may all resolve differently.
Removal safety
The uninstall command provides options for broader cleanup:
--purge
--all
--systemPotentially destructive operations are made explicit and can be reviewed with --dry-run.
The command reports when another vix binary remains available through the shell path after removal.
This can happen when several installations exist, such as one under /usr/local/bin and another in a user directory.
Instead of reporting a misleading success and leaving the user confused when vix still runs, the CLI explains that another binary is being resolved.
Fixed module activation behavior
This release fixes a conflict between the new manifest-driven module system and the older modules/* CMake fallback.
In early implementations, disabling a module in vix.app did not always prevent the legacy loader from discovering its folder and compiling it anyway.
Vix now emits the enabled module list for every vix.app project, including when that list is empty.
The legacy folder scan remains available only for classic CMake projects that do not use the application manifest module model.
As a result:
[module.auth]
enabled = falsenow reliably prevents auth from being added to the generated application target.
Fixed generated registration
vix modules add now registers new modules in vix.app automatically.
Generated service modules use the correct:
kind = "service"metadata and participate in the generated app wiring.
Backend modules compile with their generated route registration and become available through the normal application startup path.
Disabling either kind removes its route because the module no longer enters the generated build or registration code.
Fixed module test generation
Generated module tests are now created once and included in the correct build phase.
The release removes duplicate file output previously produced during some module generation paths.
Application test options are declared before module loading so each enabled module can create its test target when requested.
This makes the workflow consistent:
vix modules add auth
vix build
vix testsNo manual CMake edits are required to make the generated test visible.
Application structure
A backend can now grow around feature-oriented directories:
modules/
├── auth/
├── projects/
├── builds/
└── packages/Each module can keep its own manifest, routes, controller, implementation, migrations, and tests.
The application bootstrap remains responsible for shared runtime configuration, server startup, global middleware, and infrastructure used across modules.
Feature-specific behavior remains inside the module that owns it.
The model is intentionally internal to the application. It provides structure without requiring a distributed system, plugin runtime, or separate package for every feature.
Example workflow
Create a backend project:
vix new cloud --template backend
cd cloudAdd two modules:
vix modules add auth
vix modules add projectsDeclare the dependency of projects on auth:
[module.auth]
enabled = true
path = "modules/auth"
kind = "backend"
depends = []
[module.projects]
enabled = true
path = "modules/projects"
kind = "backend"
depends = ["auth"]Check the structure:
vix modules checkBuild and run:
vix build
vix runDisable one module:
vix modules disable projectsDuring vix dev, the manifest change triggers application regeneration and removes the disabled module from the active executable.
Validation
The App Modules workflow was validated across manifest parsing, generation, CMake integration, runtime registration, module state changes, tests, and development mode.
Coverage includes:
- parsing
[module.<name>]sections; - enabled and disabled module state;
- custom module paths;
- service and backend module kinds;
- internal dependency lists;
- automatic registration in
vix.app; vix.modulegeneration;- generated controller and route files;
- backend migration directories;
- generated test files;
ModuleRegistrygeneration;vix_app_modules.hppandvix_app_modules.cpp;- executable target integration;
- automatic route registration;
- empty enabled-module lists;
- exclusion of disabled modules;
- legacy loading compatibility for classic CMake projects;
- missing module directories;
- missing
CMakeLists.txt; - missing
vix.module; - undeclared folders;
- disabled dependencies;
- undeclared dependencies;
- circular dependencies;
- duplicate route prefixes;
- module test discovery through
vix tests; - manifest-aware rebuilds through
vix dev.
The uninstall workflow was validated for SDK profile listing, single-profile removal, complete SDK cleanup, global package removal, dry-run behavior, JSON output, explicit installation paths, and stale shell-path detection.
Compatibility
Classic CMake projects can continue to load modules through the existing modules/* convention.
The stricter enabled-module behavior applies to projects using vix.app, where the manifest is now the authoritative source of application composition.
Existing vix.app projects without module declarations remain valid. Their generated executable workflow continues without requiring a modules/ directory.
Generated modules remain ordinary C++ and CMake source directories. Developers can inspect and modify their files without relying on a hidden binary format or runtime service.
SDK uninstall commands do not remove the Vix CLI unless the broader CLI uninstall option is selected.
Existing global package installations remain compatible with the improved uninstall manifest cleanup.
Known limitations
Vix App Modules in this release are internal application modules. They are not independently published registry packages.
The first generated structures focus on routed service and backend modules. More specialized module workflows can be added later without changing the manifest foundation.
Internal dependencies are validated for declaration, activation state, and cycles, but this release does not yet provide module-level registry package declarations. External package ownership inside modules is introduced in v2.7.2.
Generated route registration assumes the standard Vix application and backend startup model. Projects with heavily customized bootstraps may need to connect the generated module registry at their own integration point.
Disabling a module removes it from compilation and generated registration, but it does not delete its source files or migration history.
Release summary
Vix.cpp v2.7.1 gives C++ applications a manifest-driven internal module structure.
Modules can be declared, generated, enabled, disabled, listed, validated, tested, and wired into the application without maintaining separate registration code in main.cpp.
Backend projects receive feature-oriented module skeletons with controllers, routes, migrations, and tests. General applications receive routed service modules connected through a small generated module registry.
vix dev now understands that application manifest changes can alter the generated build and performs the required regeneration instead of treating them like ordinary source edits.
The release also improves SDK registration and expands vix uninstall into a clearer workflow for CLI installations, SDK profiles, and global packages.
This establishes the application module foundation extended by later v2.7 releases with module-level package dependencies and generated WebSocket workflows.