Voyant
The open-source travel commerce platform for OTAs, tour operators, and DMCs.
Documentation | Website
Voyant is a complete travel commerce platform — catalog, pricing, inventory, bookings, finance, CRM, proposals, and distribution in one back office for OTAs, tour operators, and DMCs.
Getting started
Voyant runs as a resident Node application. Run it yourself, or have it run for you.
Voyant
Have the Voyant team run it for you. Provisioning, upgrades, security, and maintenance are all handled — you get the platform without operating it. A deployment can be exported to Voyant OSS at any time (details).
Voyant OSS
Voyant OSS is this repository: the whole platform under Apache-2.0, published as a container image.
docker pull ghcr.io/voyant-travel/operator:latest
docker run --rm -p 8080:8080 --env-file ./operator.env \
ghcr.io/voyant-travel/operator:latest
The server listens on PORT (default 8080) and exposes /healthz for
container probes. It needs a Postgres URL and a set of auth, session, and
integration secrets — apps/operator/.env.example
is the authoritative key list.
Every push to
mainpublishes an immutablesha-<git-sha>tag; deliberate releases publish a bare semver tag, andlatestis promoted from an already-verified release digest. Pin a semver tag or a digest in production — asha-snapshot records which commit was built, not which version was released. See Operator Image Distribution.
From source
To generate and own a project instead, use the CLI:
npm install -g @voyant-travel/cli
voyant new my-travel-app
cd my-travel-app && pnpm install
cp .env.example .env # set DATABASE_URL, auth secrets, …
pnpm db:migrate && pnpm dev
Visit the documentation to learn more.
What is Voyant?
Voyant is the back office an OTA, tour operator, or DMC runs on. It comes two ways: Voyant OSS, the complete Apache-2.0 platform you self-host, and Voyant, the same platform run for you.
What it covers:
- Catalog and products — tours, packages, charters, cruises, flights, and accommodation held as resellable inventory.
- Pricing and sellability — offers, occupancy pricing, promotions, travel credits, and channel-aware rules.
- Inventory and availability — allotments, departures, and the operational logistics behind them.
- Bookings — the full lifecycle, participants, requirements, and itinerary composition.
- Finance — invoicing, payments, supplier costs, tax, FX, and profitability.
- CRM and proposals — people, organizations, pipelines, and versioned proposals that carry a trip from sales pursuit to confirmed booking.
- Distribution and storefronts — channel distribution plus a public booking surface for customers.
It sits on a normalized travel operations data model, and each domain module contributes its own API surface, subscribers, jobs, and React components, so the platform can be extended in place.
Accommodation is held as sellable catalog inventory, for resale, packaging, and
trip composition — see
docs/architecture/accommodation-resale-boundary.md.
How it runs
Voyant runs as a resident Node process on Postgres — TanStack Start + React 19
for the dashboard, Hono for the API, Better Auth for identity, Drizzle for data
access. The modules below are assembled through the resolved deployment graph
and booted by @voyant-travel/runtime. Node is the target
for the composed application; edge-native storefront and federated surfaces keep
their own hosts. The reasoning and measurements are in
Deployment Targets and
Node Runtime Authority.
The deployable is published as ghcr.io/voyant-travel/operator.
apps/operator is the checked-in application that
exercises the whole platform in this workspace; generated projects come from the
CLI's STANDARD_NODE_STARTER contract, documented in
Standard Node Starter Acceptance.
The module surface
The platform is built from the modules below — components of one deployable, resolved together into the running application (ADR-0016).
Fourteen of them are published to npm: the *-contracts tier plus
@voyant-travel/ui, @voyant-travel/payments, @voyant-travel/schema-kit,
@voyant-travel/app-manifest, and @voyant-travel/admin-extension-sdk. Those
are the integration points for code outside this repository.
@voyant-travel/cli is
published from its own repository. Everything else is private, so the tables
below map this repository, not the npm registry; see
docs/frontend-package-strategy.md for
what may be published and why.
Core platform
| Package | Description |
|---|---|
@voyant-travel/core |
Module system, container, event bus, and adapter registration |
@voyant-travel/db |
Drizzle schemas, TypeID, and database adapters |
@voyant-travel/hono |
createApp, middleware, auth, and actor guards |
@voyant-travel/react |
Shared React provider and typed fetch client |
@voyant-travel/auth |
Better Auth wiring for the Voyant application |
@voyant-travel/auth-react |
Auth React hooks and components |
@voyant-travel/types |
Shared workspace types |
@voyant-travel/utils |
Shared utility functions |
@voyant-travel/voyant-test-utils |
Test helpers (db, http, seq, cli) |
@voyant-travel/cli |
The voyant CLI: scaffolding, generators, and db tooling |
@voyant-travel/storage |
StorageProvider abstraction (local, R2, S3) |
@voyant-travel/i18n |
Internationalization primitives |
Travel domain modules
| Package | Description |
|---|---|
@voyant-travel/catalog |
Products, tours, packages, and media |
@voyant-travel/commerce |
Pricing, offers, and sellability |
@voyant-travel/inventory |
Bookable inventory and availability |
@voyant-travel/operations |
Suppliers and operational logistics |
@voyant-travel/bookings |
Booking lifecycle and participants |
@voyant-travel/finance |
Invoicing, payments, tax, and profitability |
@voyant-travel/legal |
Contracts and policies |
@voyant-travel/notifications |
Email/SMS provider abstraction |
@voyant-travel/distribution |
Channel distribution |
@voyant-travel/relationships |
CRM: people, organizations, and pipelines |
@voyant-travel/proposals |
Proposals and trip revisions |
@voyant-travel/trips |
Trip composition and itineraries |
@voyant-travel/identity |
Contact points, addresses, and named contacts |
@voyant-travel/public-api |
Public booking-portal surface |
@voyant-travel/accommodations |
Accommodation resale inventory |
@voyant-travel/charters |
Charter products |
@voyant-travel/cruises |
Cruise products |
@voyant-travel/flights |
Flight products |
Background execution
Selected modules contribute the subscribers and jobs required for their product behavior. Jobs are enabled by the standard managed and self-hosted runtime and recover from domain-owned durable state. Customer-specific automation consumes Voyant events and invokes authenticated domain APIs from an external automation system.
UI and React families
Reusable frontend surfaces live in the matching -react package for each
domain module. Those packages own hooks, clients, providers, query keys,
view-model helpers, reusable components, and ./ui owner paths where needed.
For example, @voyant-travel/relationships-react,
@voyant-travel/proposals-react,
@voyant-travel/inventory-react,
@voyant-travel/commerce-react, and
@voyant-travel/bookings-react. Bookings requirements
live under @voyant-travel/bookings-react/requirements; checkout UI lives under
@voyant-travel/finance-react/checkout-ui. The shared admin shell lives in
@voyant-travel/admin; cross-cutting primitives in
packages/ui.
Extending the platform
Voyant keeps a small extension vocabulary: modules are the components the platform is built from, and customization happens at two seams — adapters and providers, and apps. See the taxonomy.
Adapters and providers
Adapters and providers swap a vendor or infrastructure implementation inside
the deployment. They are ordinary graph units selected through the resolved
deployment graph — object storage, KV, rate limiting, and search all resolve
this way, as does @voyant-travel/storage.
| Package | Description |
|---|---|
@voyant-travel/payments |
The payment adapter contract — initiate/status/verify, provider catalog, and remote transport. Netopia and Voyant Pay are catalog providers |
@voyant-travel/voyant-connect-adapter |
Voyant Connect supplier connectivity, on top of the external @voyant-travel/connect-sdk |
Apps
An app is a separately deployed service activated for a deployment through OAuth. App code runs entirely outside the Voyant process and never contributes migrations, routes, providers, or any other executable server code. Apps integrate through scoped APIs, events, durable webhook subscriptions, app-owned namespaced custom fields, and sandboxed admin extensions.
The deployment-local runtime for this — registration, immutable declarative
releases, consent, installation, grants, pause/revoke/uninstall — lives in
@voyant-travel/apps. Accounting and CRM integrations such
as SmartBill are apps. See
the Remote App Platform RFC.
Architecture
Voyant keeps a strict boundary between reusable business logic and deployment shells:
packages/*hold reusable business logic, schemas, services, routes, adapters, and contractsapps/*own UI, auth wiring, deployment shape, and runtime-specific configuration- Domain packages stay transport- and UI-agnostic even though the application layer uses React, TanStack Start, Hono, Better Auth, and Drizzle
- Transport adapters stay thin and call shared domain services rather than owning business logic
- Package manifests contribute required subscribers and jobs; deployment hosts provide their runtime infrastructure
- Modules are components of one deployable, not independently shipped services (ADR-0016)
Architecture decisions live in docs/adr/; domain conventions
live in docs/architecture/; per-minor migration notes
live in docs/migrations/. Start with
the unified deployment graph,
which is what resolves modules into the shipped application.
Security model
One Postgres database + one runtime per organization. Tenancy is enforced
at the deployment boundary, not by in-process middleware, so new package work
under packages/* should not add in-process tenant scoping. See
ADR-0001 for the full rationale, the
alternatives considered, and the conditions under which the decision should be
revisited.
Contributing
This repository is Voyant OSS: the domain modules, the deployable application, generated project packaging, runners, and examples.
| Area | What it contains |
|---|---|
packages/* |
Reusable business logic, schemas, services, transport adapters, and integrations |
packages/*-contracts |
Published contract packages consumed outside this repository |
apps/operator |
Checked-in Operator integration and deployable application |
apps/* |
Applications, reference/demo APIs, and the shadcn registry host |
examples/operator-demo |
Destructive and generated Operator demo fixtures |
Monorepo commands
Voyant uses pnpm workspaces and Turborepo.
| Command | Description |
|---|---|
pnpm install |
Install workspace dependencies |
pnpm build |
Build the workspace with Turborepo |
pnpm typecheck |
Run workspace typechecks |
pnpm test |
Run workspace tests |
pnpm test:bookings:integration |
Start or reuse the Docker test Postgres, ensure the bookings test schema, and run the bookings integration files serially |
pnpm lint |
Run Biome checks across the repo |
pnpm generate:schema-docs |
Regenerate SCHEMA.md from the Drizzle table definitions |
pnpm -F operator dev |
Start the Operator application on port 3300 |
Integration test database
The shared Docker test Postgres is defined in
docker-compose.test.yml.
- default host port:
5436 - override with
TEST_DATABASE_PORT - override the full connection string with
TEST_DATABASE_URL
For the bookings package, contributors can use:
pnpm test:bookings:integration
That helper starts or reuses the Docker test DB, applies starter migrations, ensures the current additive bookings-session table exists, and runs the bookings DB-backed integration files serially to avoid deadlocks from concurrent table truncation.
Community & support
- Documentation: guides, references, and concepts
- GitHub Issues: bugs and feature requests
- @voyant_travel: news and updates
Credits
Voyant is created and maintained by PixelMakers.
License
Licensed under the Apache License, Version 2.0 (Apache-2.0).