Thank you for your interest in contributing to Rix.
Rix is the official userland package layer for Vix.cpp. It provides optional libraries such as auth, CSV, debug helpers, PDF generation, and future packages for Vix.cpp applications.
This guide explains how to contribute to Rix packages, examples, documentation, tests, and package design.
Use Vix commands:
vix install
vix build
vix testsFor package dependencies, use deps in vix.app:
deps = [
"rix/rix",
]Do not put Rix packages in packages.
Keep Rix packages:
optional
focused
stable
independent
easy to use from Vix.cpp projectsRix exists to keep Vix.cpp focused.
Vix.cpp owns:
runtime
CLI
project workflow
build workflow
registry workflow
application foundation
service and deployment workflowRix owns optional userland libraries:
auth
csv
debug
pdf
future packagesA contribution should respect that separation.
Rix is an official package namespace and collection for optional Vix.cpp libraries.
Rix packages are installed through the Vix Registry:
vix add rix/rix
vix installThey are used through deps:
deps = [
"rix/rix",
]Rix is not a CLI.
Rix is not a runtime.
Rix is not the package manager.
Rix is not Vix Core.
Rix is not a standard library built into Vix.cpp.
Rix packages are optional libraries used inside Vix.cpp projects.
Every Rix package should follow one stable model:
Registry package -> rix/name
Header -> <rix/name.hpp>
Facade access -> rix.name
Namespace -> rixlib::nameExamples:
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::pdfThe unified facade package is:
rix/rixIt provides:
#include <rix.hpp>and:
rix.auth
rix.csv
rix.debug
rix.pdfYou can contribute by improving:
package APIs
bug fixes
tests
examples
documentation
README files
registry metadata
error messages
security notes
package designStart small when possible.
A focused fix is easier to review than a large mixed change.
Make sure the project builds:
vix install
vix buildRun tests:
vix testsRun relevant examples:
vix run examples/01_basic.cppUse Vix commands for Rix projects.
Do not use direct CMake or Ninja commands unless you are specifically debugging build internals.
Clone the repository:
git clone https://github.com/rixcpp/rix.git
cd rixInstall dependencies:
vix installBuild:
vix buildRun tests:
vix testsUse short branch names.
Examples:
fix/pdf-save-error
docs/auth-security
feat/csv-options
test/debug-formatKeep one topic per branch.
Use clear commit messages.
Examples:
fix(pdf): handle empty output path
docs(auth): add session security notes
test(csv): cover row filter options
feat(debug): add format append helperGood commit messages explain the package and the reason.
Keep code simple and explicit.
Prefer readable APIs over clever abstractions.
Use C++20.
Use clear names.
Keep public APIs small.
Keep implementation details hidden.
Prefer explicit result types for expected failures.
Public includes should use Rix package headers.
Facade usage:
#include <rix.hpp>Independent package usage:
#include <rix/pdf.hpp>
#include <rix/csv.hpp>
#include <rix/debug.hpp>
#include <rix/auth.hpp>Do not require users to include internal headers for normal workflows.
Use package namespaces:
namespace rixlib::pdf
{
}Examples:
rixlib::auth
rixlib::csv
rixlib::debug
rixlib::pdfThe global facade object exposes modules:
rix.auth
rix.csv
rix.debug
rix.pdfPublic APIs should make common workflows short.
Good:
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto saved = rix.pdf.save(doc, "hello.pdf");Avoid making users start from internals.
Less good as a first API:
PdfObjectWriter writer;
XrefTable xref;
FontRegistry fonts;Internals can exist, but the common public API should stay simple.
Expected failures should use explicit result or status objects.
For operations that return values:
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(bytes.error()),
bytes.error().message());
return 1;
}
const auto &data = bytes.value();For operations that only succeed or fail:
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;
}Never call value() before checking success.
Packages with domain failures should expose stable error codes.
Examples:
rixlib::auth::AuthErrorCode
rixlib::pdf::PdfErrorCodeError helpers should be exposed through package modules:
rix.auth.error.to_string(error)
rix.auth.error.is(error, code)
rix.pdf.error.to_string(error)
rix.pdf.error.is(error, code)Use stable error codes for application decisions.
Use error messages for diagnostics.
Be careful with packages related to auth, passwords, sessions, tokens, crypto, or user data.
Do not log:
plain-text passwords
password hashes
raw tokens
session ids
private keys
secretsAuth changes should keep safe defaults.
Security-sensitive code should have tests and documentation.
rix.debug is useful for examples, tests, formatting, printing, and inspection.
For real Vix application logs, prefer:
vix::logDo not design production application logging around:
rix.debug.logUse debug helpers for examples and small tools.
Rix packages belong in deps.
Correct:
deps = [
"rix/pdf",
]Wrong:
packages = [
"rix/pdf",
]deps is for Vix Registry dependencies.
packages is for CMake package discovery.
If a package needs another Rix package, add it explicitly.
Example:
deps = [
"rix/debug",
]Independent packages should avoid depending on rix/rix unless there is a strong reason.
If a package only needs one feature, depend on that package directly.
When adding a package to the unified facade, make sure:
the independent package works first
the facade member name follows rix.name
the package has a stable public module
feature macros still work
default facade behavior still works
docs are updated
examples are updated
tests are addedThe facade supports feature macros.
If no feature macro is defined, all mounted modules are enabled.
If one or more feature macros are defined, only selected modules are mounted.
Examples:
#define RIX_ENABLE_PDF
#include <rix.hpp>#define RIX_ENABLE_CSV
#define RIX_ENABLE_DEBUG
#include <rix.hpp>Available macros include:
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDFWhen adding a new facade module, add its feature macro and test it.
Docs should start with the facade when possible:
#include <rix.hpp>and:
rix.pdf
rix.auth
rix.csv
rix.debugThen show independent usage later:
#include <rix/pdf.hpp>
auto pdf = rixlib::pdf::module();This keeps the public docs consistent.
Use home-folder examples:
mkdir -p ~/rix-example
cd ~/rix-exampleDo not use /tmp in docs unless there is a specific reason.
Some systems or user environments may not behave the same with /tmp.
Examples should be complete and runnable.
Good example:
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto saved = rix.pdf.save(doc, "hello.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "hello.pdf");
return 0;
}Run examples with:
vix run example.cppIf Rix is not available globally:
vix install -g rix/rix
vix run example.cppFor project examples, use:
vix new my-app --app
cd my-app
vix add rix/rix
vix install
vix build
vix runShow deps clearly:
deps = [
"rix/rix",
]Do not put Rix packages in packages.
Add tests for code changes.
Tests should cover:
basic success path
invalid input
edge cases
error codes
public headers
version helpers
result handling
facade usage when relevant
independent usage when relevantRun:
vix testsAdd examples when a feature needs explanation.
Examples should show real usage, not internals first.
For PDF:
examples/pdf/basic
examples/pdf/text
examples/pdf/table
examples/pdf/drawing
examples/pdf/error-handlingFor auth:
examples/auth/memory-register-login
examples/auth/password-hash
examples/auth/session-refresh-logout
examples/auth/token-issueFor CSV and debug:
examples/csv
examples/debugUpdate the README when a contribution changes public behavior.
A README should explain:
what the package does
how to install it
how to include it
a basic example
facade usage
independent usage
error handling when relevant
license
repository linkStart with public usage.
Do not start with internals.
If the repository uses a changelog, update it for user-facing changes.
Group changes by type:
Added
Changed
Fixed
Deprecated
Removed
SecurityKeep entries short and clear.
Before opening a pull request, check:
vix install passes
vix build passes
vix tests passes
examples still run
docs are updated
README is updated if needed
public API is stable and simple
errors are explicit
sensitive values are not logged
Rix packages are in deps, not packagesA good pull request description includes:
what changed
why it changed
how it was tested
any API impact
any documentation impact
any security impactExample:
## Summary
Fixes PDF save error handling for empty output paths.
## Testing
- vix build
- vix tests
- vix run examples/pdf/error_handling.cpp
## Notes
No breaking API changes.Reviews should focus on:
correctness
API simplicity
error handling
test coverage
docs clarity
security implications
Vix/Rix separation
backward compatibilityPrefer specific feedback.
Avoid broad rewrites unless they improve the public API or correctness.
Avoid breaking public APIs without a strong reason.
If a breaking change is necessary:
explain why
update docs
update examples
update tests
consider a migration note
use a version bump that reflects the changeKeep application code stable.
Before adding a new Rix package, check:
Does it solve one clear problem?
Is it optional?
Does it belong outside Vix Core?
Can it work independently?
Can it later mount into rix/rix?
Does it follow rix/name?
Does it expose <rix/name.hpp>?
Does it use namespace rixlib::name?
Does it have a simple module?
Does it have examples and tests?If the answer is yes, it fits the Rix model.
A new package can use this shape:
name/
CMakeLists.txt
README.md
LICENSE
vix.json
include/
rix/
name.hpp
name/
Version.hpp
NameModule.hpp
core/
detail/
src/
NameModule.cpp
examples/
01_basic.cpp
tests/
name_tests.cppEvery package should expose:
#include <rix/name.hpp>Example shape:
#ifndef RIXCPP_NAME_INCLUDE_RIX_NAME_HPP_INCLUDED
#define RIXCPP_NAME_INCLUDE_RIX_NAME_HPP_INCLUDED
#include <rix/name/NameModule.hpp>
#include <rix/name/Version.hpp>
namespace rixlib::name
{
[[nodiscard]] inline constexpr NameModule module() noexcept
{
return NameModule{};
}
}
#endifPackages should expose version helpers.
Example:
rix.name.version()
rix.name.version_major()
rix.name.version_minor()
rix.name.version_patch()
rix.name.version_number()Independent package namespace:
rixlib::name::version()
rixlib::name::version_major()
rixlib::name::version_minor()
rixlib::name::version_patch()
rixlib::name::version_number()Before a release:
update version
update changelog
run vix install
run vix build
run vix tests
run examples
check docs
check README
tag release
publish registry metadata
test install from a clean projectAfter publishing, verify:
vix registry sync
vix add rix/name
vix installDo not open a public issue for sensitive security problems.
Report security problems privately through the project maintainer contact or the repository security policy if one is available.
Security-sensitive reports may include:
auth bypass
password hashing issues
token leakage
session validation issues
secret exposure
unsafe defaultsWrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]Prefer Vix commands:
vix build
vix tests
vix runStart from public usage:
#include <rix.hpp>
auto doc = rix.pdf.document();Then document internals later if needed.
Rix is not the runtime.
Vix.cpp owns runtime behavior.
Rix is not the package manager.
Vix owns the package workflow.
Do not log:
passwords
password hashes
tokens
session ids
private keys
secretsPrefer:
mkdir -p ~/rix-exampleover:
mkdir -p /tmp/rix-exampleUse Vix commands:
vix install
vix build
vix testsUse deps for Rix packages:
deps = [
"rix/rix",
]Follow the Rix package model:
Registry package -> rix/name
Header -> <rix/name.hpp>
Facade access -> rix.name
Namespace -> rixlib::nameKeep packages independent.
Keep public APIs small.
Use explicit results for expected failures.
Document facade usage first.
Do not log sensitive values.
Read the package model and package checklist.
Next: Package model