Application Model
A Vix.cpp application is a native C++ project with a defined entry point, project description, runtime workflow, build workflow, and operational model.
Vix.cpp does not treat an application as only a collection of .cpp files. It treats it as a software unit that can be created, configured, built, run, tested, packaged, diagnosed, and deployed through a consistent workflow.
The application model can be summarized like this:
source code
-> application description
-> modules and dependencies
-> configuration
-> runtime workflow
-> build output
-> production workflowThis model is what allows a Vix.cpp project to move from a small local application to a production service without changing the basic way developers operate it.
The application starts with intent
When a developer creates a project, the first question should not be only:
Where is the CMakeLists.txt?The better first question is:
What kind of application is this?A backend service, a CLI tool, a game, a reusable library, and a P2P node do not need the same starting structure.
Vix.cpp uses templates to give the project an initial shape:
vix new api --template backendvix new tool --appvix new mathlib --libThe template does not finish the architecture for you. It gives the project a correct starting point so the application can grow from a clear foundation.
The application root
The application root is the directory where Vix.cpp resolves the project.
A backend project may look like this:
api/
├── vix.app
├── vix.json
├── vix.lock
├── .env.example
├── production.env.required
├── src/
├── tests/
├── migrations/
├── public/
└── data/From this directory, the main commands should feel natural:
vix dev
vix run
vix build
vix check --tests
vix deployThe root matters because Vix.cpp reads project files from there and writes local state there.
Common project-local state includes:
.vix/
build/
build-ninja/
build-release/
dist/These directories are generated state. They are not the source model of the application.
Project inputs
Vix.cpp supports two main project inputs:
CMakeLists.txt
vix.appThe resolution order is:
1. CMakeLists.txt
2. vix.appIf CMakeLists.txt exists, Vix.cpp uses the existing CMake project.
If there is no CMakeLists.txt and vix.app exists, Vix.cpp uses the vix.app manifest.
This rule protects existing CMake projects while giving new applications a simpler path.
vix.app
vix.app is the simple application manifest for Vix.cpp.
It describes what the application is and what needs to be built.
Example:
name = api
type = executable
standard = c++23
sources = [
src/main.cpp,
src/app/AppFactory.cpp,
src/routes/HealthRoutes.cpp,
]
include_dirs = [
src,
]
modules = [
core,
json,
http,
]This file answers basic build questions:
What is the application called?
What kind of target is it?
Which C++ standard does it use?
Which source files are compiled?
Which include directories are used?
Which Vix.cpp modules are required?For many applications, this is enough to start.
Vix.cpp can generate the internal CMake project from this description.
The generated file lives under:
.vix/generated/app/CMakeLists.txtDevelopers should edit vix.app, not the generated CMake file.
Why vix.app matters
Many C++ applications do not need advanced CMake logic at the beginning.
A developer should be able to describe a normal application with a small manifest instead of starting from a full build system definition.
The difference is practical.
Instead of beginning with:
cmake_minimum_required(...)
project(...)
add_executable(...)
target_include_directories(...)
target_link_libraries(...)a simple application can begin with:
name = api
type = executable
sources = [...]
modules = [...]CMake is still available when needed. But it does not have to be the first wall every application developer hits.
When to use CMake directly
Use CMakeLists.txt when the build itself needs advanced control.
Examples include:
custom targets
complex native dependencies
manual install rules
platform-specific build logic
advanced linking
custom code generation
large multi-target projects
exported CMake packages
toolchain-specific behaviorWhen CMakeLists.txt exists, Vix.cpp respects it.
The model is:
vix.app = simple application manifest
CMakeLists.txt = advanced build definition
Vix.cpp = one workflow over bothThis is important for experienced C++ developers. Vix.cpp is not a closed ecosystem. It works with the native C++ build ecosystem.
vix.json
vix.app describes the application build model.
vix.json describes the project workflow model.
It can contain project metadata, dependency information, tasks, registry configuration, and production workflow settings.
Example:
{
"name": "api",
"version": "0.1.0",
"type": "application",
"deps": [],
"tasks": {
"dev": "vix dev",
"build": "vix build",
"test": "vix check --tests",
"fmt": "vix fmt"
}
}For production, vix.json can also describe service and health behavior:
{
"production": {
"service": {
"name": "api",
"user": "vix",
"working_dir": "/home/vix/apps/api",
"command": "vix run",
"env_file": "/home/vix/apps/api/.env"
},
"health": {
"local": "http://127.0.0.1:8080/health",
"public": "https://api.example.com/health"
}
}
}Keep the distinction clear:
vix.app = application build model
vix.json = project workflow model
vix.lock = exact dependency modelvix.lock
vix.lock records the exact dependency state of the project.
If vix.json describes what the project needs, vix.lock records what was actually resolved.
After cloning a project, use:
vix installThis installs the locked dependency versions.
Do not use update when the goal is reproducibility.
vix install = reproduce the locked state
vix update = change the locked stateThis distinction matters for teams, CI, release builds, and production systems.
Source layout
A serious backend should not keep all logic inside main.cpp.
A maintainable backend can use a layout like this:
src/
├── main.cpp
├── app/
│ ├── AppFactory.hpp
│ └── AppFactory.cpp
├── config/
│ ├── Config.hpp
│ └── Config.cpp
├── routes/
│ ├── HealthRoutes.hpp
│ └── HealthRoutes.cpp
├── middleware/
├── validation/
├── services/
├── database/
└── errors/The rule is simple:
main.cpp should start the application, not contain the whole application.Small main.cpp
A clean entry point can look like this:
#include <vix.hpp>
#include "app/AppFactory.hpp"
#include "config/Config.hpp"
int main()
{
api::Config config = api::Config::load(".env");
vix::App app = api::create_app(config);
app.run(config.server_port());
return 0;
}This keeps the responsibilities separate.
Configuration is loaded by the config layer.
The application is created by the app factory.
Routes are registered elsewhere.
main.cpp remains readable.
Application factory
An application factory creates and configures the Vix app.
Header:
#pragma once
#include <vix.hpp>
#include "config/Config.hpp"
namespace api
{
vix::App create_app(const Config &config);
}Implementation:
#include "app/AppFactory.hpp"
#include "routes/HealthRoutes.hpp"
namespace api
{
vix::App create_app(const Config &config)
{
vix::App app;
register_health_routes(app, config);
return app;
}
}This makes application setup easier to test and easier to extend.
Routes
Routes should be grouped by feature.
Example:
routes/
├── HealthRoutes.hpp
├── AuthRoutes.hpp
├── UserRoutes.hpp
└── AdminRoutes.hppA health route should exist early:
GET /healthExample response:
{
"ok": true,
"service": "api",
"status": "healthy"
}This route is useful locally, but it also matters in production:
vix health local
vix health public
vix deployA production workflow should be able to verify that the application is alive.
API response shape
A backend should use a predictable response shape.
Success:
{
"ok": true,
"data": {}
}List:
{
"ok": true,
"count": 3,
"data": []
}Error:
{
"ok": false,
"error": "validation_failed",
"message": "email is required"
}A stable response shape helps clients, tests, logs, API documentation, and language models that need to understand examples from the documentation.
Configuration
Configuration should come from the environment.
A backend template should include:
.env.example
production.env.requiredExample .env.example:
APP_ENV=development
SERVER_HOST=127.0.0.1
SERVER_PORT=8080
SERVER_TLS_ENABLED=false
VIX_LOG_LEVEL=info
VIX_LOG_FORMAT=kv
VIX_COLOR=auto
DATABASE_ENGINE=sqlite
DATABASE_DEFAULT_NAME=./data/app.db
JWT_SECRET=change-me
SESSION_SECRET=change-meCheck local configuration:
vix env checkCheck production configuration:
vix env check --productionThe application should not hardcode secrets, production paths, hostnames, or deployment-specific values.
Modules
A Vix.cpp application is composed from modules.
Example:
modules = [
core,
json,
http,
validation,
middleware,
db,
log,
]Modules make the application explicit.
If the app uses JSON, declare JSON.
If the app uses HTTP, declare HTTP.
If the app uses database support, declare database support.
A good application model should avoid hidden guessing.
Dependencies
Registry packages are different from built-in modules.
Use registry packages when the project needs reusable external packages.
Typical workflow:
vix registry sync
vix search json
vix add softadastra/json
vix installAfter adding a dependency, project state can change in:
vix.json
vix.lock
.vix/deps/
.vix/vix_deps.cmakeAfter cloning the project, the expected command is:
vix installThat should reproduce the locked dependency state.
Tasks
Tasks belong in vix.json.
Example:
{
"tasks": {
"dev": "vix dev",
"build": "vix build",
"test": "vix check --tests",
"fmt": "vix fmt",
"release": "vix build --preset release && vix check --tests"
}
}Tasks are useful for repeated workflows.
They should not hide important behavior behind unclear names.
Good task names describe what the command does.
Tests
A real application should include tests.
Basic structure:
tests/
├── test_health.cpp
├── test_validation.cpp
└── test_auth.cppGenerate a test skeleton:
vix make test HealthRoutesRun tests:
vix testsOr run broader validation:
vix check --testsThe application model is incomplete without tests.
Static files
Some applications serve public files.
Example:
public/
├── favicon.ico
├── robots.txt
└── assets/Keep served files outside src/.
src/ = C++ source code
public/ = served public contentThis keeps the layout understandable.
Database files
For SQLite applications, keep database files outside source directories.
Example:
data/
└── app.dbMigrations belong in a dedicated folder:
migrations/
├── 2026_01_01_000001_create_users.up.sql
└── 2026_01_01_000001_create_users.down.sqlDatabase commands may include:
vix db status
vix db migrate
vix db backupFor ORM workflows:
vix orm status --db api --dir ./migrations
vix orm migrate --db api --dir ./migrationsGenerated files
Use vix make to generate files inside an existing project.
Examples:
vix make class User --in src/domain --namespace api::domain
vix make struct Claims --in src/auth --namespace api::auth
vix make enum Status --in src/domain
vix make function parse_token --in src/auth
vix make test AuthService
vix make config app --websocket --databaseThe model is:
vix new = create a project
vix make = add files to a projectDo not confuse project creation with file generation.
Runtime arguments
Application arguments are separated from Vix arguments with --.
Example:
vix run -- --port 8080The first part belongs to Vix.cpp.
The second part belongs to the application.
vix run [vix options] -- [application arguments]This distinction matters in scripts, CI, and replay workflows.
Replay
If a run is important to reproduce, record it.
vix run --replayReplay the latest run:
vix replay lastReplay the latest failed run:
vix replay failedThe application model includes replay because real applications fail.
When they fail, the exact run context matters.
Development mode
Development mode watches files and rebuilds intelligently.
vix devTypical behavior:
source change -> rebuild
header change -> rebuild
config change -> reconfigure and rebuild
ignored path -> do nothingIgnored paths include:
.git
.vix
build
build-dev
build-ninja
build-release
node_modules
.cache
.idea
.vscodevix dev is for active development.
It is not the production process.
Build output
Build output should not pollute the source model.
Common build folders:
build/
build-ninja/
build-release/Generated Vix state:
.vix/Package output:
dist/Clean local project state:
vix cleanReset local project state and reinstall dependencies:
vix resetPackaging
A project can be packed when it is ready to be distributed.
vix packVerify the package:
vix verifyCache a verified package:
vix cache --path ./dist/api@1.0.0For application developers, packaging may not be the first concern.
For libraries, SDKs, release artifacts, and distribution workflows, it becomes important.
Production configuration
A production-ready application should have production configuration in vix.json.
Important sections include:
production.service
production.proxy
production.health
production.logs
production.deployThese sections allow Vix.cpp to run commands such as:
vix service init
vix proxy nginx init
vix health
vix logs
vix deployProduction should not be a separate manual world.
It should be part of the application model.
Local vs production
Local development:
vix devProduction service management:
vix service init
vix service statusLocal health check:
vix health localPublic health check:
vix health publicDeployment:
vix deployThe same application moves through different workflows.
The application model stays consistent.
A complete backend template
A serious backend template should look like this:
api/
├── vix.app
├── vix.json
├── vix.lock
├── .env.example
├── production.env.required
├── README.md
├── src/
│ ├── main.cpp
│ ├── app/
│ ├── config/
│ ├── routes/
│ ├── middleware/
│ ├── validation/
│ ├── database/
│ ├── services/
│ └── errors/
├── migrations/
├── tests/
├── public/
└── data/This is the kind of application Vix.cpp should make easy to create:
vix new api --template backendApplication checklist
A Vix.cpp application should be able to answer these questions:
What is the application name?
What type of target is it?
What source files are compiled?
What modules are used?
What dependencies are installed?
What environment variables are required?
How is the application run locally?
How is it built?
How is it tested?
How is it checked?
How is it deployed?
How are logs read?
How is health checked?If the project cannot answer these questions, the application model is incomplete.
These questions also make the project easier for humans, tools, CI systems, and language models to understand.
What you should remember
A Vix.cpp application is not only source code.
It is:
source files
-> application description
-> modules
-> dependencies
-> runtime workflow
-> build workflow
-> tests
-> production workflowUse:
vix new api --template backendfor a real backend starting point.
Use vix.app for the simple application manifest.
Use vix.json for project workflow, dependencies, tasks, registry metadata, and production configuration.
Use:
vix installto reproduce dependencies.
Use:
vix devto develop.
Use:
vix deploywhen the application is ready for production.