Next.js

@firma/pay uses ecash-lib (WASM). Next.js App Router must not statically prerender pages that import the library at build time — the prerender step loads WASM and fails.

Mark the route dynamic

Add export const dynamic = 'force-dynamic' to any server page that renders PayWithFirma (directly or via a client child):

app/checkout/page.tsx
// app/checkout/page.tsx
export const dynamic = 'force-dynamic';

import { Checkout } from './Checkout';

export default function CheckoutPage() {
  return <Checkout />;
}

Client component

Keep PayWithFirma in a 'use client' component and import the stylesheet there:

app/checkout/Checkout.tsx
'use client';

import '@firma/pay/firma-pay.css';
import { PayWithFirma } from '@firma/pay';

export function Checkout() {
  return (
    <PayWithFirma
      receiverUsername="merchant"
      orderId="VP9G"
      amount="10.00"
      currency="USD"
      onPaymentFinalized={(txid) => console.log('Paid!', txid)}
    />
  );
}

transpilePackages

If you consume @firma/pay from a monorepo workspace package, add it to transpilePackages in next.config.ts:

next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  transpilePackages: ['@firma/pay'],
};

export default nextConfig;

See the live example in this repo at cf/firma/pay.firma.cash or try the Demo.