@voyant-travel/flights is the flights vertical for OTA, tour-operator, and DMC deployments. Flights are modeled as supplier integrations and sourced inventory: Voyant is not an airline or a flight-operator system, and the module never tries to be one.
Flights are unlike every other vertical. There is no slow-moving inventory to pre-project, no marketing copy to overlay on “LHR to JFK on BA177”, and no semantic-search use case (customers specify route, dates, and passengers, then expect live offers). The module reflects that: it adopts only the catalog-plane surfaces that add real value (booking snapshots, provenance, webhooks, source disconnection) and opts out of the rest (search-index projection, editorial overlays, embeddings, drift detection). Live multi-connection fan-out replaces the index.
The package is opt-in. Templates that need flights (a tour-package vertical, a corporate-travel storefront, a cruise reseller offering coordinated flights) register it; the rest skip it entirely.
Key concepts
These terms come from the shared glossary and the flight contract.- The flight lifecycle: search, price, book, order. A flight provider integrates by implementing five core methods on the
FlightConnectorAdapter:searchFlights(returns offers),priceOffer(revalidates an offer),bookFlight(creates an order, held or ticketed),getOrder, andcancelOrder. If any of the five cannot be implemented, the connection is not a flight connection. - Slice-based search. A search request carries
slices, where each slice is{ origin, destination, departureDate }. One slice is a one-way, two is a round-trip, three or more is a multi-city or open-jaw. Slices generalize cleanly where flat origin / destination / return-date shapes cannot. - Intent-driven booking. The book request carries a
paymentIntentdiscriminated union.{ type: "hold" }returns a confirmed order to ticket later,{ type: "card", ... }returns a ticketed order, and{ type: "ticket_on_credit" }covers the GDS agency model. The default is hold. Consumers declare intent rather than branching on capability discovery. - Capability-gated methods. Alongside the five core methods sit optional ones declared per connection: holds, seat maps, seat selection, ancillaries, check-in, exchange, refund, void, special service requests, and branded fares. An adapter that does not declare a capability stubs the method with
CAPABILITY_NOT_SUPPORTED. - Itinerary fingerprint. A deterministic key derived from a
FlightOffer’s segments (carrier codes, flight numbers, airports, times, cabin). Two providers selling the same flight produce identical fingerprints, which is how fan-out deduplicates. - Booking snapshot. At book time the module captures the frozen
FlightOfferplusFlightOrder, the segments, the PNR, the fare breakdown, and the source pointer into abooking_catalog_snapshotrow. This is the one catalog-plane surface flights fully adopt, because refunds, exchanges, and audits months later need the frozen offer and order.
How it relates to the catalog and Connect
The flight contract shapes (FlightConnectorAdapter, FlightOffer, FlightOrder, MergedFlightOffer, capability ids, paymentIntent) mirror voyant-cloud’s connect-flight-contract so adapters stay portable between Voyant Cloud and a Voyant Catalog flight integration. Connect flights provide the connector ecosystem (Hisky, Amadeus, Duffel, Sabre, Travelport NDC, and operator-built GDS adapters), each implementing the same contract this module orchestrates.
What it owns
- The flight contract:
./contract/types(offers, orders, segments, requests, capability ids, thepaymentIntentunion),./contract/adapter(theFlightConnectorAdapterinterface), and./contract/schemas(Zod runtime schemas for HTTP, queue, RPC, and adapter boundaries). - Multi-connection orchestration:
./orchestration/fingerprint(the itinerary fingerprint helper) and./orchestration/fan-out(parallel search across all of an operator’s flight connections, per-provider timeout and circuit breaker, dedupe by fingerprint, merged result with a cheapest offer plus alternates). - Booking-time snapshot capture under
./snapshot, which builds the catalog plane’s capture input from aFlightOfferandFlightOrderpair. - The reference-data layer: the
ReferenceDataProvidercontract under./reference/contract, plus shipped implementations including./reference/local-postgres(plain tables in the operator’s own database, no external service) and./reference/static-bundle. - The
/v1/{admin,public}/flights/searchand/v1/{admin,public}/flights/orders/*routes, mounted by templates that need flights.
Working with it
Multi-connection fan-out search
An agency wired to several providers gets one merged result set without writing fan-out, dedupe, or partial-failure handling. One slow or failing provider does not tank the search; whichever providers respond come back, and the rest are flagged per connection.Validate at a wire boundary
Use the shipped Zod schemas rather than re-declaring runtime validators when you expose the contract over HTTP, queues, or RPC.Book with an explicit payment intent
Hydrate reference data from the operator’s own database
Airlines, airports, and aircraft are global IATA-coded reference data, not flight catalog data. They sit behind a swappable provider. The simplest valid first-party option is plain Postgres tables in the operator’s own database, with no external service and no network call.Links to other modules and Connect
- catalog and bookings. Flights opt into the booking snapshot graph: a booked flight writes a
booking_catalog_snapshotrow withentity_module: "flights"and the frozen offer, order, segments, fare breakdown, and source pointer. - provenance and webhooks. Every flight order carries the standard provenance tuple, and
catalog.booking.committedand.cancelledevents fire on the standard webhook pipeline. - source disconnection. If a provider connection is hard-disconnected, preserved booking snapshots stay queryable for refund and audit while live capability against that source stops.
- Connect. Flight adapters reach the module through Connect’s connector ecosystem or as operator-built packages. Because the contract is borrowed from voyant-cloud’s
connect-flight-contract, the same adapter works on both sides. See the Connect SDK.
React package
@voyant-travel/flights-react is the flights client tier: headless data hooks and a fetch client at the root and ./hooks, ./client, and ./query-keys, plus styled UI and full page compositions under ./ui. The styled subpaths add optional peers (@voyant-travel/ui, @voyant-travel/relationships-react for CRM-backed contact and billing pickers, and the finance checkout UI).
FlightsPage renders search, filtering, the per-leg round-trip picker, the offer detail sheet, and the booking handoff. The route owns URL validation and navigation:
FlightBookingPage renders the repricing, ancillaries, seat-map, passenger, billing, payment, and confirmation flow. Router behavior, booking submission, and payment capabilities are callbacks or slots, so applications keep deployment-specific ownership.
Next steps
Connect SDK
The flight connector ecosystem and the shared contract.
Modules overview
How verticals compose into a Voyant app.
Data model
How schemas, links, and snapshots are authored.
Glossary
The shared domain language flights speaks.