@voyant-travel/storage package, a small provider abstraction that gives portable code one contract and lets the deployment choose the backend.
This page covers the platform storage provider interface and its built-in backends. It is the in-process abstraction you wire into a self-hosted deployment. It is distinct from the managed Cloud storage service, which Voyant runs for you. Cross-link below.
One provider contract
Everything in the package targets a single interface,StorageProvider, from @voyant-travel/storage/types:
StorageUploadBody accepts an ArrayBuffer, a Uint8Array, or a Blob. upload returns a StorageObject carrying the object key and a public url (an empty string when the object is private and only reachable through signedUrl). get returns null when the key is absent.
Portable module code targets this interface. The backend is a deployment choice, not a fork of the module.
The service wrapper
Most deployments use exactly one storage backend, socreateStorageService(provider) from @voyant-travel/storage/service wraps a single provider as a named StorageService:
upload / delete / signedUrl / get surface as the provider, plus a provider reference. It is a thin convenience, not an orchestration layer.
Built-in backends
The package ships three providers. Each is created by a factory and satisfies the sameStorageProvider contract.
Local
createLocalStorageProvider() keeps objects in an in-memory Map held in a closure. It is the right backend for unit tests and for running workflows locally without touching remote storage. Data does not survive the process.
R2
createS3CompatibleStorageProvider({ bucket }) binds to a Cloudflare R2 bucket binding (for example env.MEDIA_BUCKET). The binding handles authentication at the Worker runtime boundary, so no credentials live in this layer.
R2 bindings do not mint signed URLs by themselves. The R2 provider adds a publicUrl(key) method for permanent public URLs (requires publicBaseUrl, a public custom domain or a Worker route that proxies the bucket). For time-limited access, configure a signer.
S3 and S3-compatible
createS3CompatibleStorageProvider({ region, bucket, accessKeyId, secretAccessKey }) signs every request with AWS SigV4 using Web Crypto, so it needs no AWS SDK. It accepts an optional sessionToken for temporary credentials.
For S3-compatible services (MinIO, Backblaze B2, DigitalOcean Spaces, Wasabi, or R2’s S3 API), set a custom endpoint. forcePathStyle defaults to true for the widest compatibility; set it to false for virtual-hosted-style URLs. signedUrl presigns a GET URL with SigV4.
The SigV4 signing primitives, signRequest and presignUrl, are also exported directly from @voyant-travel/storage/lib/sigv4 for advanced use. They are verified against the AWS canonical test vectors.
Package exports
Framework storage versus Cloud storage
This package is the in-process abstraction you assemble into a deployment yourself: you pick a provider, supply the bucket or credentials, and own the operational surface. Cloud storage is the managed alternative. Voyant runs the backend, provisioning, and access for you, so you do not wire up an R2 binding or carry S3 credentials. Reach for the platform package when you self-host and want to choose and control the backend. Reach for Cloud storage when you want it managed.Next steps
Cloud storage
The managed storage service, the counterpart to this in-process abstraction.
Configuration
How a deployment chooses and wires its storage backend.
Services
Where module code calls into a storage provider.
Glossary
The shared vocabulary behind the storage model.