Using Rix in a Vix Project
This guide shows how to use Rix packages inside a Vix.cpp project.
Rix packages are installed through the Vix Registry and added to the deps section of vix.app.
Use this guide when you already have a Vix application or when you want to create one with vix new.
The short version
Create a Vix app:
vix new my-app --app
cd my-appAdd Rix:
vix add rix/rix
vix installUse Rix in code:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix");
return 0;
}Make sure vix.app contains:
deps = [
"rix/rix",
]What this guide covers
This guide explains:
how to add Rix to a Vix project
where Rix packages go in vix.app
how to use the unified facade
how to use independent packages
how to use Rix from an app template
how to use Rix from a simple file
common mistakesCreate a new Vix app
Use:
vix new rix-app --app
cd rix-appThis creates a Vix application project.
A Vix application has a manifest file:
vix.appThe manifest describes sources, include directories, dependencies, packages, links, and resources.
Add the unified Rix facade
For most applications, add the unified facade package:
vix add rix/rix
vix installThis gives access to:
#include <rix.hpp>and:
rix.auth
rix.csv
rix.debug
rix.pdfAdd Rix to vix.app
Rix packages are Vix Registry dependencies.
They belong in deps:
deps = [
"rix/rix",
]Do not put Rix packages in packages.
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for packages installed by Vix.
packages is for CMake package discovery.
Minimal vix.app
A minimal app using Rix can look like this:
name = "rix-app"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
defines = [
"VIX_BACKEND_APP=1",
"VIX_APP_NAME=rix-app",
]
compile_options = [
"$<$<CXX_COMPILER_ID:MSVC>:/W4>",
"$<$<CXX_COMPILER_ID:MSVC>:/permissive->",
"$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall>",
"$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wextra>",
"$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wpedantic>",
]
link_options = [
]
compile_features = [
"cxx_std_20",
]
packages = [
"vix",
]
links = [
"vix::vix",
]
resources = [
]The important Rix part is:
deps = [
"rix/rix",
]Basic app code
Put this in:
src/main.cpp#include <rix.hpp>
int main()
{
rix.debug.print("Hello from Rix inside a Vix project");
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
rix.debug.print("rows:", table.size());
return 0;
}Build and run:
vix build
vix runUse Rix inside a Vix backend app
A Vix backend app can use both Vix and Rix.
Example:
#include <vix.hpp>
#include <rix.hpp>
int main()
{
vix::App app;
app.get("/", [](vix::Request &, vix::Response &res) {
res.text("Hello from Vix.cpp and Rix");
});
app.run();
return 0;
}In this model:
Vix.cpp owns the app runtime
Rix provides optional librariesUse rix.pdf inside a Vix route
#include <vix.hpp>
#include <rix.hpp>
int main()
{
vix::App app;
app.get("/report.pdf", [](vix::Request &, vix::Response &res) {
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
res.status(500).json({
"ok", false,
"error", rix.pdf.error.to_string(bytes.error()),
"message", bytes.error().message()});
return;
}
res.header("Content-Type", "application/pdf");
res.header("Content-Disposition", "inline; filename=\"report.pdf\"");
res.send(bytes.value());
});
app.run();
return 0;
}Use rix.pdf.write in routes when the PDF should be sent as HTTP response bytes.
Use rix.pdf.save when the PDF should be written to disk.
Use rix.auth inside a Vix route
#include <vix.hpp>
#include <rix.hpp>
int main()
{
vix::App app;
auto auth = rix.auth.memory();
app.post("/register", [&](vix::Request &, vix::Response &res) {
auto registered = auth.register_user({
"ada@example.com",
"correct-password"});
if (registered.failed())
{
res.status(400).json({
"ok", false,
"error", rix.auth.error.to_string(registered.error()),
"message", registered.error().message()});
return;
}
res.json({
"ok", true,
"email", registered.value().email()});
});
app.run();
return 0;
}Use memory auth for examples, tests, and local development.
Use database-backed stores for durable applications.
Use rix.csv in a Vix project
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n");
rix.debug.print("rows:", table.size());
for (const auto &row : table)
{
rix.debug.inspect(row);
}
return 0;
}For real Vix application logs, prefer the Vix logging system.
For examples and small tools, rix.debug.print is fine.
Use rix.debug in a Vix project
#include <rix.hpp>
int main()
{
rix.debug.print("Hello", "Rix");
const auto message = rix.debug.format(
"Package: {}",
"rix/rix");
rix.debug.print(message);
rix.debug.inspect(message);
return 0;
}rix.debug is for examples, formatting, printing, and inspection.
For production application logs, prefer Vix logging.
Use independent packages
You do not always need the unified facade.
If the project only needs PDF, install only:
vix add rix/pdf
vix installIn vix.app:
deps = [
"rix/pdf",
]Then include:
#include <rix/pdf.hpp>Example:
#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 independent rix/pdf");
auto saved = pdf.save(doc, "hello.pdf");
return saved.ok() ? 0 : 1;
}Facade vs independent package
Facade usage:
Package -> rix/rix
Header -> <rix.hpp>
Access -> rix.*Independent usage:
Package -> rix/name
Header -> <rix/name.hpp>
Access -> rixlib::name::module()Use the facade for normal apps.
Use independent packages when the project only needs one package.
Use feature macros
The facade can be limited with feature macros.
Example:
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
rix.debug.print("PDF module loaded");
return 0;
}When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
Available macros include:
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDFDefault facade behavior
If no feature macro is defined, all currently mounted modules are enabled.
This means:
#include <rix.hpp>gives access to:
rix.auth
rix.csv
rix.debug
rix.pdfThis keeps simple examples short.
Add several independent packages
If you do not want rix/rix, you can add several independent packages manually:
vix add rix/csv
vix add rix/debug
vix add rix/pdf
vix installIn vix.app:
deps = [
"rix/csv",
"rix/debug",
"rix/pdf",
]Then include package headers directly:
#include <rix/csv.hpp>
#include <rix/debug.hpp>
#include <rix/pdf.hpp>For most applications, prefer rix/rix when using several packages.
Use Rix from a simple file
You can also use Rix from a single file.
Create a folder:
mkdir -p ~/rix-single-file
cd ~/rix-single-file
touch main.cppAdd:
#include <rix.hpp>
int main()
{
rix.debug.print("Hello from a single file");
return 0;
}Run:
vix run main.cppIf Rix is not available globally:
vix install -g rix/rix
vix run main.cppSingle file with independent package
For PDF only:
mkdir -p ~/rix-single-pdf
cd ~/rix-single-pdf
touch pdf.cppAdd:
#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, "single.pdf");
return saved.ok() ? 0 : 1;
}Run:
vix run pdf.cppIf needed:
vix install -g rix/pdf
vix run pdf.cppApp template workflow
If you create an app with:
vix new my-app --appthen add Rix with:
vix add rix/rix
vix installThe app should keep Rix in:
deps = [
"rix/rix",
]Then use:
#include <rix.hpp>inside src/main.cpp or any other source file included by the app.
Library project workflow
If you are building a C++ library and only need one Rix package, use the independent package.
Example:
vix add rix/pdf
vix installIn vix.app or the project manifest:
deps = [
"rix/pdf",
]Then:
#include <rix/pdf.hpp>Use this when the library should not depend on the full facade.
Build and run
After changing dependencies, run:
vix install
vix build
vix runIf you only changed source code:
vix build
vix runUse Vix commands for Vix projects.
Tests
If your project has tests, use:
vix testsKeep Rix dependencies in deps so tests and application builds resolve them consistently.
Updating Rix packages
To update dependencies, use the Vix workflow:
vix installIf your registry index needs refresh:
vix registry sync
vix installUse this when a package was recently released or the local registry data is stale.
Removing a Rix package
Use:
vix remove rix/pdf
vix installThen remove it from your source code includes and usage.
If you remove rix/rix, replace:
#include <rix.hpp>with the independent headers you still need.
Common project layout
A small Vix project with Rix can look like this:
my-app/
vix.app
src/
main.cpp
include/
public/
views/
storage/vix.app owns the build inputs.
deps owns Vix Registry dependencies.
Source files include Rix headers.
Common mistakes
Putting Rix in packages
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]Forgetting vix install
After adding a package, run:
vix installWithout it, generated dependency files may not be updated.
Installing rix/pdf but including <rix.hpp>
If your code uses:
#include <rix.hpp>then use:
vix add rix/rix
vix installIf your code uses:
#include <rix/pdf.hpp>then use:
vix add rix/pdf
vix installMixing facade and independent styles
Avoid this without a reason:
#include <rix.hpp>
#include <rix/pdf.hpp>Prefer one style per file.
Facade:
#include <rix.hpp>Independent:
#include <rix/pdf.hpp>Expecting Rix to replace Vix.cpp
Rix does not replace Vix.cpp.
Vix.cpp still owns:
project creation
build workflow
run workflow
runtime
HTTP and WebSocket layer
services
deployment workflow
registry commandsRix provides optional libraries.
Using rix.debug as production logging
rix.debug is useful for examples and small tools.
For real Vix application logs, prefer the Vix logging system.
Calling value() before checking results
Many Rix APIs return explicit results.
Wrong:
auto bytes = rix.pdf.write(doc);
res.send(bytes.value());Correct:
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
return;
}
res.send(bytes.value());What you should remember
For most Vix applications, use:
vix add rix/rix
vix installThen:
#include <rix.hpp>and:
rix.auth
rix.csv
rix.debug
rix.pdfIn vix.app, use:
deps = [
"rix/rix",
]For independent package usage, use:
vix add rix/pdf
vix installThen:
#include <rix/pdf.hpp>and:
deps = [
"rix/pdf",
]Vix.cpp owns the project and runtime.
Rix provides optional userland packages.
Next step
Continue with configuration.
Next: Configuration