Skip to content

Installation

Prerequisites

  • Node.js ≥ 18.17
  • pnpm (the repo is a pnpm workspace; pnpm@10.24 is pinned via packageManager). npm/yarn work for consuming the published packages, but the monorepo scripts assume pnpm.
  • React ≥ 18 if you use @payfanout/react (declared as a peer dependency).

Which packages do I need?

Install only the side(s) you run. @payfanout/core comes in transitively but can be added explicitly. Adapters come as a client/server pair per PSP — swap <psp> below for the package names in Payment providers, which lists every shipped adapter. You don't have to install them all, add only the PSP(s) you use.

Server side

bash
pnpm add @payfanout/server @payfanout/adapter-<psp>-server

Server adapters carry the secret credentials. Every REST-based one is edge-runtime compatible (WebCrypto only, no Node builtins) and runs on Cloudflare Workers / Next.js edge routes; the Stripe adapter is the exception, because it bundles the Stripe Node SDK (stripe) as a dependency.

Client side (React)

bash
pnpm add @payfanout/react @payfanout/adapter-<psp> react react-dom

The client adapters have no npm dependency on the PSP browser SDKs: each provider's SDK is loaded lazily via a <script> tag only when its adapter is actually mounted. There is nothing extra to pnpm add for them, and no SDK downloads during SSR.

Environment variables

Keys never live in code, and every adapter requires an explicit environment: "sandbox" | "live", it is never inferred from a key prefix.

The exact variables are per PSP, and each one's set-up guide lists its own — names, where to obtain each value, and which are optional. Start from Payment providers and open the guide for the PSP you're wiring up. Three things hold across all of them:

  • Env-var names are yours, not the adapter's. They differ from the adapter's config field names (a PAYSAFE_SESSION_KEY variable feeding sessionSigningKey, say); the guides show the mapping.
  • Not every value comes from the PSP. Adapters that encode a stateless session sign it with a secret you generate (openssl rand -hex 32) and never share with the provider.
  • Client-side vars must be VITE_-prefixed for Vite to expose them to the browser bundle. Only ever put browser-safe public keys there — a secret in a VITE_ variable is a secret you have published.

A pinned provider apiVersion is code, not configuration: where a PSP has one, the adapter pins it explicitly rather than reading it from the environment.

Never commit secrets

.env and .env.* are git-ignored on purpose. Sandbox or live, keys never enter the repo.

Next: set up your PSP

Package install is only half the job. The per-PSP setup guides take you from credentials to a working payment, obtaining keys, wiring both adapter halves, registering the webhook, and test values:

  • Payment providers, the shared four-step shape plus the table of every shipped adapter, linking to that PSP's own set-up guide.
  • Writing an adapter, install a PSP we don't ship yet.

Building from source (contributing)

Working on PayFanout itself, or need an unreleased change from develop? Use the workspace directly:

bash
git clone <this-repo>
cd <repo>
pnpm install          # installs every workspace package
pnpm run build        # tsc-emits each package to dist/ (published exports point here)
pnpm run check        # typecheck + lint + package-boundary check + all tests

Inside the monorepo, packages resolve via workspace:* and their exports point at the TypeScript source (./src/index.ts), a TS-aware bundler or tsx consumes them directly, no build required (this is how the demo runs). The compiled dist/ only exists after pnpm run build; you need it to consume a package from another local project via a file: / link: dependency pointing at packages/<name>.

Verify your setup

bash
pnpm run check   # green here means types, lint, boundaries, and tests all pass

Then jump to Server usage or, if you just want to see everything working end-to-end, run the demo app described in Getting started.

Try the demo app

The demo (examples/demo) shows every shipped PSP behind identical UI, switchable at runtime:

bash
pnpm --filter payfanout-demo dev:server   # Express API + webhook endpoints on :4242
pnpm --filter payfanout-demo dev:web      # Vite dev server (proxies /api and /webhooks)

Set the variables for whichever PSPs you want live — each one's set-up guide lists them, and examples/demo/server.mts shows the full set the demo reads. Don't forget the VITE_-prefixed client keys, which a bare <PSP>_* glob would miss. Unset variables fall back to inert placeholders, so the app boots but real charges need the real keys.