Skip to main content
This page explains how a Voyant application is put together. Read it once before you start building and the rest of the documentation will make more sense.

The big idea

Voyant is a set of headless domain modules that you compose into an application. Each module owns one slice of the travel business, such as catalog, bookings, or finance. A module brings its own database schema, services, and HTTP routes, plus an optional React package for its UI. You pick the modules you need, wire them together with links, and deploy the result as a single application per organization. The framework keeps a strict boundary:
  • Packages hold reusable business logic, schemas, services, routes, and adapters. They are framework-agnostic.
  • Starters and app shells own UI, auth wiring, deployment shape, and runtime configuration.
This means the same domain logic runs whether you deploy to your own infrastructure or to Voyant Cloud, and whether your UI is the first-party React shell or something you build yourself.

The stack

The first-party starters run on a serverless-first stack:
LayerTechnology
RuntimeCloudflare Workers
DatabasePostgreSQL, accessed through Drizzle ORM
API transportHono, with optional framework route helpers
FrontendTanStack Start and React
AuthBetter Auth in the starters; core packages stay auth-provider agnostic
Core packages do not depend on any of these choices. They expose plain services and an HTTP contract, so you can host them differently if you need to.

Modules

A module is a package such as @voyant-travel/bookings or @voyant-travel/catalog. Each one is self-contained:
  • A Drizzle schema for its tables.
  • Domain services that enforce the rules of that subdomain.
  • HTTP routes exposing those services over the API.
  • A matching -react package (for example @voyant-travel/bookings-react) with hooks, clients, query keys, and reusable UI.
  • A contracts package (for example @voyant-travel/bookings-contracts) describing the wire types shared between server and client.
You add a module by installing it and registering its schema and routes, or you generate a brand new one with the CLI. See Modules for the full catalog and the generator. Modules stay decoupled, but real travel data is relational: a person belongs to organizations, a booking references a quote, a product references a place. Voyant models these cross-module relationships with links. A link is a declarative relationship between an entity in one module and an entity in another. You declare it once and the framework can emit the link table DDL for you:
voyant generate link crm.person products.product --right-list
This keeps foreign-key style relationships explicit and discoverable without forcing every module to import every other module. The voyant db sync-links command emits the SQL or a generated Drizzle schema for all declared links.

Transport and contracts

Every module exposes its services over HTTP using Hono. The wire shape of those routes lives in a dedicated -contracts package, so the server implementation and the client SDK share one source of truth for request and response types. The -react packages consume those contracts to give you typed hooks instead of hand-written fetch calls. This contract-first approach is the same idea behind the public SDKs: a typed client generated against a stable API surface.

Workflows

Long-running and multi-step processes, such as a reserve-and-confirm booking flow or a batch of booking reminders, run as durable workflows. A workflow is authored as plain TypeScript with steps, sleeps, and retries. Its state is durable, so it survives restarts and can resume exactly where it left off. Workflows run on your own infrastructure (self-host Node and Postgres) or on Voyant Cloud’s hosted runtime, using the same authoring SDK either way. See Workflows for how to write and run them.

Surfaces: storefront and admin

Two ready-made surfaces sit on top of the modules:
  • The storefront is the customer-facing booking experience: discovery, product detail, checkout, and self-service.
  • The admin is the staff-facing operations console: managing quotes, bookings, inventory, finance, and the rest of the back office.
Both are assembled from the same domain modules and their React packages. See Storefront and Admin.

The deployment and security boundary

Voyant’s tenancy model is deliberately simple: one Postgres database and one runtime per organization. Isolation is enforced at the deployment boundary, not by in-process middleware that filters rows by tenant id. This is a foundational decision. It removes a whole class of cross-tenant data-leak bugs, keeps queries simple, and makes each customer’s data physically separate. When you deploy to Voyant Cloud, the platform provisions and manages that per-organization runtime and database for you.

Where to go next

Glossary

The shared travel vocabulary every module uses.

Project structure

What a scaffolded Voyant project actually contains.

Module catalog

Every domain module and what it owns.

Workflows

Author durable, step-based orchestration.