An evidence-first genealogy program. Every fact is a recorded claim — who asserted it, when, from which source, and with what confidence. The family tree you read is a conclusion derived from those claims, not a database edited in place. Nothing is ever silently overwritten: a correction is a new assertion that supersedes an old one, and both stay in the record.
Vitni is Old Norse for witness.
- Evidence and conclusions are separate layers. The event log is the evidence: each entry is an assertion by a named operator, carrying its date, reason, confidence and citations. The entities you browse — persons, families, places, sources — are projections rebuilt from that log at any time. Two researchers can disagree in the record without one of them losing.
- Corrections keep the trail intact. Retracting or superseding an assertion references it by identity and appends a new entry. There is no destructive edit and no "who changed this?" that the program cannot answer.
- Plugins are sandboxed WebAssembly components. Import, export and plugin-contributed UI run as
wasm32-wasip2components with deny-by-default capabilities — a plugin reaches the network, the media library or the command surface only where it was granted that capability, and signed first-party bundles are distinguished from untrusted ones. - Localized down to the message. Interface text resolves through Fluent, including labels a plugin contributes, so a plugin's form is translated like the rest of the app. English and Norwegian ship today.
Pre-1.0 and usable. The domain model, persistence, import/export, the desktop GUI, the geography and
map views, and the plugin trust model are implemented; DNA breadth and a server-backed web frontend
are the remaining work. Release artifacts are Linux-first — a tarball, a .deb and an AppImage
(see docs/release.md). The CLI and the desktop GUI are both thin frontends over
the same application layer, so they stay in step by construction; two known gaps in either direction
are tracked in docs/issues.md rather than papered over.
Pre-1.0 data notice. Upgrading between pre-1.0 versions is not migration-safe. Event payloads change without upcasters and configuration files owe no backwards compatibility (ADR 0018 §3, ADR 0015), so a workspace or a
config.tomlwritten by an earlier build may not open in a later one. Keep the authoritative copy of your genealogy data elsewhere, treat a Vitni workspace as re-creatable, and export (GEDCOM or Gramps XML) before upgrading. Projections are not the concern here — those rebuild themselves from the event log.
The pedigree tool charts a focus person's ancestors and says plainly which lines are unresearched rather than leaving a gap:
The geography view plots every place in the workspace, as of a year you choose:
(All three images are of invented demo data, regenerated from the running GUI by one command — see
docs/development.md.)
Needs a current stable Rust toolchain via rustup; the wasm32-wasip2 target
installs itself from rust-toolchain.toml.
# Create a workspace, add a person, list what is there
cargo run -p vitni-cli -- init demo /path/to/demo-ws
cargo run -p vitni-cli -- --workspace demo person create --given Ada --surname Lovelace
cargo run -p vitni-cli -- --workspace demo person list
# Build the import/export and UI plugins into target/plugins/
cargo xtask build-plugins
# Run the desktop GUI against that workspace
VITNI_WORKSPACE=demo cargo run -p vitniA workspace is a directory with a workspace.toml manifest, referred to by name; global settings
live in ~/.config/vitni/config.toml. The CLI has one subcommand-bearing verb per record type
(person, family, place, source, citation, event, note, media, tag, repository,
dna-test, dna-match, research-note) plus init, rebuild, import, export and plugin.
The GUI renders through a system webview and therefore needs WebKitGTK on Linux; the CLI needs no
extra system libraries. Platform-by-platform setup is in
docs/development.md.
Interface language follows the system locale, or set it explicitly:
LANGUAGE=no cargo run -p vitni-ui-dioxus --features desktopThe entity vocabulary — persons, families, events, places, sources, citations, repositories, media, notes, tags, plus DNA tests, DNA matches and research notes — is informed by Gramps v6 and by other tools and standards in this space, including webtrees, Gramps Web, GEDCOM and GEDCOM-X. Interchange today is GEDCOM and Gramps XML, both as plugins. The model is a clean-room reimplementation: no Gramps source is copied.
docs/data-model.md is the reference for the entities, the command and event
catalog, and the provenance envelope; docs/adr/ records the architecture decisions and
docs/roadmap.md the plan.
A Cargo workspace. Domain logic never depends on a frontend, and no UI framework type appears above
the renderer crate, so a second frontend is additive rather than a rewrite. The WASM plugin
components under plugins/* are excluded from the workspace — they build only for wasm32-wasip2,
via cargo xtask build-plugins.
| Crate | Role |
|---|---|
vitni-core |
Domain model and event-sourcing engine. Pure: no I/O, no clock, no user-facing strings. |
vitni-db |
Persistence: event store, projections, migrations. SQLite by default, Postgres feature-gated. |
vitni-app |
Coordination: config, workspace lifecycle, the impure inputs (clock, ids, operator) and the use-cases returning frontend-neutral DTOs. |
vitni-cli |
The terminal frontend, and the headless vitni-cli binary. |
vitni-ui |
Framework-agnostic presentation: view-models, navigation intents, Fluent resolution, the plugin-UI vocabulary. |
vitni-ui-dioxus |
A Dioxus renderer over vitni-ui. |
vitni |
The vitni binary: the GUI with no arguments, the CLI with any. |
vitni-plugin-host |
Wasmtime component host: capability grants, fuel and memory limits, bundle signature verification. |
vitni-i18n |
Fluent plumbing: the workspace → shared → embedded override chain and locale fallback. |
vitni-interchange |
The format-neutral leaf value vocabulary shared by the interchange formats. |
vitni-gedcom, vitni-gramps-xml, vitni-digitalarkivet |
Pure parse/emit crates behind the corresponding plugins. |
xtask |
Repository task runner (cargo xtask …), not shipped. |
cargo build --workspace
cargo nextest run --workspace --all-features --lib --bins --tests
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo fmt --all
cargo deny --all-features check # advisories, licences, bans
cargo xtask check # i18n completeness, CSS tokens, input-handling guard
cargo xtask build-plugins
cargo xtask gui-pass # drive the real GUI headless and assert over screenshots
cargo xtask screenshots # regenerate the images above from the running GUIPass
--workspace(or-p <crate>):default-membersis the CLI alone, so a barecargo testskips most of the repo.
The workspace denies unwrap_used, panic, todo and friends at deny level, and silencing them
with #[allow(…)] is itself denied — warnings get fixed, not suppressed. Every user-facing string
goes through Fluent, and every UI change updates docs/mockups/ in the same commit.
Platform setup, the two GUI test layers and the rest of the conventions are in
docs/development.md.
Split by layer:
- The interchange crates —
vitni-interchange,vitni-gedcom,vitni-gramps-xml,vitni-i18nand the bundled plugin sources — areMIT OR Apache-2.0(LICENSE-MIT,LICENSE-APACHE), so anything can reuse them, including a GPLv2-only project. - The application is
AGPL-3.0-or-later(LICENSE-AGPL), with an additional permission under section 7: a WebAssembly component that talks to the host only through the versioned plugin interface is not required to be AGPL. Third-party plugins, including proprietary ones, are welcome.
NOTICE has the crate-by-crate mapping, and
ADR 0034 records why the
split is shaped this way; the longer analysis is in
docs/research/licensing-and-monetization.md.
A commercial licence is available for anyone who needs to embed the application layer in a closed
product — COMMERCIAL.md covers what it does and does not include, and the cases
that need no licence at all.
Contributions come in under the grant in CONTRIBUTING.md, which also explains
why that grant is as broad as it is.
CONTRIBUTING.md covers how a change should be shaped and what CI checks it;
participation is under CODE_OF_CONDUCT.md (Contributor Covenant 3.0). Found a
vulnerability? Do not open a public issue — SECURITY.md has the private route, the
scope, and what to expect.



