Package Model
This guide explains the Rix package model.
Rix is organized as a collection of independent packages.
Each package can be used through the unified Rix facade or directly as an independent package.
The goal is simple:
install only what you need
use one stable naming model
keep Vix.cpp focused
keep Rix packages optionalThe short version
A Rix package follows this model:
Registry package -> rix/name
Header -> <rix/name.hpp>
Facade access -> rix.name
Namespace -> rixlib::nameExample:
Registry package -> rix/pdf
Header -> <rix/pdf.hpp>
Facade access -> rix.pdf
Namespace -> rixlib::pdfThe unified facade package is:
rix/rixIt provides:
#include <rix.hpp>and the global facade object:
rixWhat a Rix package is
A Rix package is an optional library installed through the Vix Registry.
Examples:
rix/auth
rix/csv
rix/debug
rix/pdfEach package owns a focused area.
For example:
rix/auth -> authentication helpers
rix/csv -> CSV parsing and writing
rix/debug -> debug printing, formatting, inspection
rix/pdf -> PDF document generationRix packages are userland libraries.
They are not built into Vix Core.
What rix/rix is
rix/rix is the unified facade package.
It groups mounted Rix packages behind one public object:
rixExample:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix");
auto doc = rix.pdf.document();
return 0;
}The facade makes application code cleaner:
rix.auth.memory()
rix.csv.parse(...)
rix.debug.print(...)
rix.pdf.document()Two ways to use a package
There are two supported usage styles.
Use the unified facade:
#include <rix.hpp>Then:
rix.pdf.document()Or use an independent package:
#include <rix/pdf.hpp>Then:
auto pdf = rixlib::pdf::module();For most documentation and application examples, prefer the unified facade.
Facade usage
Install the unified package:
vix add rix/rix
vix installIn vix.app:
deps = [
"rix/rix",
]Use:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix");
return 0;
}This is the normal Rix style.
Independent package usage
Install only the package you need:
vix add rix/pdf
vix installIn vix.app:
deps = [
"rix/pdf",
]Use:
#include <rix/pdf.hpp>
int main()
{
auto pdf = rixlib::pdf::module();
auto doc = pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix/pdf");
auto saved = pdf.save(doc, "hello.pdf");
return saved.ok() ? 0 : 1;
}Use this style when a project only needs one package and does not need the unified facade.
Registry package names
Rix Registry packages use this pattern:
rix/nameExamples:
rix/auth
rix/csv
rix/debug
rix/pdf
rix/rixThe package name should be short, stable, and lowercase.
Use:
vix add rix/name
vix installExample:
vix add rix/pdf
vix installHeader names
Independent package headers use:
#include <rix/name.hpp>Examples:
#include <rix/auth.hpp>
#include <rix/csv.hpp>
#include <rix/debug.hpp>
#include <rix/pdf.hpp>The unified facade uses:
#include <rix.hpp>Facade names
Facade access uses:
rix.nameExamples:
rix.auth
rix.csv
rix.debug
rix.pdfThe facade should expose the public API that applications are expected to use.
Namespace names
Rix package namespaces use:
rixlib::nameExamples:
rixlib::auth
rixlib::csv
rixlib::debug
rixlib::pdfTypes live in package namespaces.
Facade members expose package modules.
Example:
rixlib::pdf::Table table;
auto doc = rix.pdf.document();Package naming table
| Package | Header | Facade | Namespace |
|---|---|---|---|
rix/auth | <rix/auth.hpp> | rix.auth | rixlib::auth |
rix/csv | <rix/csv.hpp> | rix.csv | rixlib::csv |
rix/debug | <rix/debug.hpp> | rix.debug | rixlib::debug |
rix/pdf | <rix/pdf.hpp> | rix.pdf | rixlib::pdf |
rix/rix | <rix.hpp> | rix.* | rixlib |
Dependency location in vix.app
Rix packages are Vix Registry dependencies.
They go in deps:
deps = [
"rix/rix",
]Do not put Rix packages in packages.
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
Minimal Vix app with Rix
name = "my-app"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]Then in src/main.cpp:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix");
return 0;
}Build and run:
vix build
vix runPackage independence
Each Rix package should be usable independently.
For example, rix/pdf should be usable without pulling the full facade:
#include <rix/pdf.hpp>This keeps packages focused and reusable.
The facade package rix/rix should mount those independent packages for convenient application usage.
Facade mounting
The unified facade mounts available packages as members.
Example shape:
class Rix
{
public:
rixlib::csv::Csv csv{};
rixlib::debug::Debug debug{};
rixlib::auth::AuthModule auth{};
rixlib::pdf::PdfModule pdf{};
};Then:
inline constexpr rixlib::Rix rix{};Application code uses:
rix.csv
rix.debug
rix.auth
rix.pdfFeature macros
The facade can be made lighter with feature macros.
If no RIX_ENABLE_* macro is defined, the facade enables all mounted modules by default.
This keeps simple code working:
#include <rix.hpp>If at least one macro is defined, only selected modules are mounted.
Example:
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
rix.debug.print("PDF ready");
return 0;
}Available macros include:
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDFWhen to use rix/rix
Use rix/rix when:
you want the public facade
you want one include
you use several Rix packages
you are writing application code
you are writing documentation examples
you want rix.auth, rix.csv, rix.debug, rix.pdfInstall:
vix add rix/rix
vix installUse:
#include <rix.hpp>When to use an independent package
Use an independent package when:
you only need one package
you are building a focused library
you want smaller dependency scope
you do not need the global rix facadeExample:
vix add rix/pdf
vix installThen:
#include <rix/pdf.hpp>Package API design
A Rix package should expose a simple public module.
For example, rix/pdf exposes:
rix.pdf.document()
rix.pdf.save(...)
rix.pdf.write(...)
rix.pdf.make_text(...)
rix.pdf.error.to_string(...)The public module should keep common workflows short.
More detailed types can stay in the package namespace:
rixlib::pdf::Document
rixlib::pdf::Page
rixlib::pdf::Table
rixlib::pdf::Color
rixlib::pdf::TextStyleThis keeps the facade simple while still allowing advanced control.
Result and status pattern
Packages that can fail should prefer explicit results.
Example from rix/pdf:
auto saved = rix.pdf.save(doc, "output.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}Example from rix/auth:
auto registered = auth.register_user({
"ada@example.com",
"correct-password"});
if (registered.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(registered.error()),
registered.error().message());
return 1;
}This keeps expected failures visible and avoids hiding normal errors behind exceptions.
Error module pattern
Packages with domain errors should expose error helpers through the package module.
Examples:
rix.auth.error.to_string(error)
rix.pdf.error.to_string(error)This gives applications one stable place to convert errors to readable strings.
Version helpers
Packages can expose version helpers.
Example:
rix.pdf.version()
rix.pdf.version_major()
rix.pdf.version_minor()
rix.pdf.version_patch()Version helpers are useful for diagnostics, examples, and compatibility checks.
Debug package rule
rix/debug is useful for examples, formatting, printing, and inspection.
For real Vix application logs, prefer the Vix logging system.
Use:
rix.debug.print(...)
rix.debug.eprint(...)
rix.debug.format(...)
rix.debug.inspect(...)for documentation examples and small tools.
Use Vix logging for production application logs.
Package docs style
Documentation should normally show the public facade first:
#include <rix.hpp>Then:
rix.pdf.document()
rix.auth.memory()
rix.csv.parse(...)
rix.debug.print(...)Independent package usage can be shown later as an alternative:
#include <rix/pdf.hpp>Then:
auto pdf = rixlib::pdf::module();This keeps documentation consistent.
Single-file usage
For small experiments:
mkdir -p ~/rix-package-model
cd ~/rix-package-model
touch main.cppAdd:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix");
return 0;
}Run:
vix run main.cppIf Rix is not available globally:
vix install -g rix/rix
vix run main.cppProject usage
For real projects:
vix new my-app --app
cd my-app
vix add rix/rix
vix installThen use:
#include <rix.hpp>and keep:
deps = [
"rix/rix",
]Build and run:
vix build
vix runAdding a new Rix package
A new Rix package should follow the same model.
For a package named json, the expected shape would be:
Registry package -> rix/json
Header -> <rix/json.hpp>
Facade access -> rix.json
Namespace -> rixlib::jsonThe independent package should be usable alone:
#include <rix/json.hpp>The facade package can mount it later:
rix.jsonThe package should remain optional.
New package checklist
Before adding a package, check:
Is the package optional?
Is the name short and stable?
Does it fit the rix/name model?
Can it be used independently?
Can it be mounted into rix/rix?
Does it expose a simple public module?
Does it keep internals hidden?
Does it return explicit results for expected failures?
Does it belong in userland instead of Vix Core?If the answer is yes, it fits the Rix package model.
What belongs in Vix.cpp
Vix.cpp should own:
CLI workflow
project creation
build and run workflow
registry install workflow
runtime foundation
HTTP and WebSocket runtime
service and deployment workflow
core backend infrastructureExample commands:
vix new
vix add
vix install
vix build
vix run
vix testsWhat belongs in Rix
Rix should own optional application-level libraries:
auth
csv
debug helpers
pdf generation
future userland packagesRix packages should help applications without making Vix.cpp heavier.
Common mistakes
Calling Rix a package manager
Rix is not the package manager.
Vix owns the package workflow:
vix add rix/rix
vix installCalling Rix a runtime
Rix is not the runtime.
Vix.cpp owns the runtime.
Rix packages are libraries used inside the application.
Putting Rix in packages
Wrong:
packages = [
"rix/pdf",
]Correct:
deps = [
"rix/pdf",
]Using different naming models per package
Avoid:
@rix/name
rix_name
RixName
vix/nameUse the stable model:
rix/name
<rix/name.hpp>
rix.name
rixlib::nameMaking every package part of rix/rix too early
Independent packages should work first.
Mount into the facade when the public API is stable enough.
Exposing internals first
Application docs should not start from writer internals or low-level implementation details.
Start from the facade:
rix.pdf.document()Then document advanced types later.
What you should remember
Rix packages use one model:
Registry package -> rix/name
Header -> <rix/name.hpp>
Facade access -> rix.name
Namespace -> rixlib::nameUse rix/rix for the unified facade:
vix add rix/rix
vix installUse:
#include <rix.hpp>and:
rix.auth
rix.csv
rix.debug
rix.pdfUse independent packages when needed:
vix add rix/pdf
vix installand:
#include <rix/pdf.hpp>Always put Rix packages in deps:
deps = [
"rix/rix",
]Next step
Continue with package rules.
Next: Package rules