Plugins no longer exist. Voyant used to have a generic plugin kind; it is retired, and a workspace package that declares
voyant.kind: "plugin" now fails the architecture verification. Everything that used to be a plugin is an adapter, a provider, an extension, or an app. If you are migrating, the mapping is at the bottom of this page.Which one do I need?
Provider
You want to replace one concrete implementation with another behind an existing contract. Payments, notifications, object storage, search.
Adapter
You want to talk to a specific external system, and that integration owns more than a single contract: routes, webhooks, subscribers, or several providers at once.
Extension
You want to change how an existing module behaves, not swap an implementation. See Extensions.
App
You are adding a genuinely new capability with its own records and lifecycle. Build it as an app that runs outside the deployment.
The short test: if the question is “how do I swap one implementation for another?”, the answer is a provider. If the package exists primarily to talk to an external system, it is an adapter, even when it also ships providers.
Providers
A provider implements a narrow contract for one execution seam and hides the vendor behind it. Nothing calling the contract should be able to tell which provider is selected. Providers are first-class deployment graph units:package.json#voyant.kindis"provider"- the graph manifest uses
schemaVersion: "voyant.provider.v1"
Roles, not vendors
A provider role is defined by what it does, not by who supplies it. Object storage is one role with built-in valuesmemory and s3-compatible — AWS S3, Cloudflare R2, Google Cloud Storage’s XML API, MinIO and similar all configure the s3-compatible value through endpoint and credential settings rather than getting a role each.
This matters when you write application code: modules resolve logical stores such as media and documents. They never resolve a vendor bucket or a runtime binding. A custom storage package declares a selected storage.object provider factory and returns the same logical-store resolver contract.
Payments works the same way. @voyant-travel/payments defines the adapter contract — initiate, status, verify — plus the provider catalog and remote transport. Netopia and Voyant Pay are entries in that catalog, not bespoke integrations wired into the booking flow.
See Choose or swap a provider for the mechanics.
Adapters
An adapter connects Voyant to an external vendor or service. It is the right shape when the integration is broader than a single contract. Adapters are first-class deployment graph units:package.json#voyant.kindis"adapter"- the graph manifest uses
schemaVersion: "voyant.adapter.v1"
- one or more providers
- a small extension over an existing module
- route or webhook wiring
- subscriber or job wiring owned by the integration package
@voyant-travel/voyant-connect-adapter is the reference example: it brings Connect supplier connectivity into a deployment on top of the external Connect SDK.
Selection happens in the graph
Neither seam is a runtime plugin registry. Adapters and providers are ordinary units in the resolved deployment graph, selected when the deployment is composed. Object storage, key-value, rate limiting, and search all resolve this way. Two consequences worth knowing up front:- A standard module cannot be dropped or replaced. Substitution happens at adapters and providers, never at business modules. A deployment gets the same bookings module as everyone else; what it can change is which payment provider that module ends up calling.
- Runtime contributors must declare every returned port on the owning graph unit. A package cannot quietly contribute a capability it did not declare.
Migrating from plugins
If you have a package that predates the retirement of the plugin kind, it maps to one of these:
Accounting and CRM integrations such as SmartBill are apps, not adapters, because their code runs outside the Voyant process entirely. That distinction is the subject of the next page.
Choose or swap a provider
The step-by-step version.
Apps
The other seam: code that runs outside the deployment.