npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@palpluss/paylink

v1.3.0

Published

Embed a Palpluss payment link in any website — modal or inline

Readme

@palpluss/paylink

Embed a Palpluss payment link into any website — as a modal overlay or an inline iframe — with two lines of code.

import { pay } from '@palpluss/paylink'
const result = await pay('your-paylink-id')

React is optional. The core pay() function is pure DOM with zero dependencies.


Table of Contents


How It Works

Your page                          Palpluss
─────────────────────────────      ──────────────────────
pay('abc-123')
  │
  ▼
Creates full-screen overlay
Injects <iframe src="https://link.palpluss.com/abc-123?embed=1">
  │
  │  ◄──── postMessage: RESIZE ──────────────── iframe adjusts height
  │  ◄──── postMessage: PAYMENT_SUCCESS ─────── payment complete
  │
  ▼
cleanup() — removes overlay, resolves Promise
  1. pay() creates a modal overlay and injects an iframe pointing to https://link.palpluss.com/{id}?embed=1.
  2. The embedded payment page communicates back via window.postMessage.
  3. On success the Promise resolves with { txId, amount, phone }. On close/cancel it rejects.

The iframe origin is https://link.palpluss.com — your page never handles raw payment credentials.


Installation

# npm
npm install @palpluss/paylink

# pnpm
pnpm add @palpluss/paylink

# yarn
yarn add @palpluss/paylink

React peer dependencies are optional — only needed if you import @palpluss/paylink/react.

# only if you use the React component
npm install react react-dom

Quick Start

import { pay } from '@palpluss/paylink'

const result = await pay('abc-123')
// result → { txId: 'TXN_...', amount: 500, phone: '2547...' }

API Reference

pay(paylinkId, options?)

Opens a full-screen modal containing the payment iframe.

Returns a Promise<PaymentResult> that:

  • resolves when the customer completes payment
  • rejects with Error('Payment modal closed by user') when the modal is dismissed

| Parameter | Type | Required | Description | |---|---|---|---| | paylinkId | string | Yes | The paylink ID from your Palpluss dashboard | | options | PayOptions | No | Callbacks (see below) |

PayOptions

| Option | Type | Description | |---|---|---| | onSuccess | (data: PaymentResult) => void | Called immediately when payment succeeds, before the Promise resolves | | onClose | () => void | Called when the user dismisses the modal without paying |

const result = await pay('abc-123', {
  onSuccess: (data) => console.log('paid', data),
  onClose:   ()     => console.log('modal closed'),
})

openModal(paylinkId, options, resolve, reject)

Low-level function used internally by pay(). Exposed for advanced use cases where you need direct control of the Promise lifecycle.

Returns a cleanup() function that tears down the modal immediately.

import { openModal } from '@palpluss/paylink'

const cleanup = openModal(
  'abc-123',
  {},
  (result) => console.log('resolved', result),
  (err)    => console.log('rejected', err),
)

// force-close from outside:
cleanup()

<PalplussPayment> (React)

Import from @palpluss/paylink/react. Renders the payment iframe inline — no overlay, no modal — so you control layout and placement.

import { PalplussPayment } from '@palpluss/paylink/react'

<PalplussPayment
  id="abc-123"
  onSuccess={({ txId, amount }) => console.log(txId, amount)}
  className="my-payment-frame"
/>

| Prop | Type | Required | Description | |---|---|---|---| | id | string | Yes | Paylink ID | | onSuccess | (data: PaymentResult) => void | No | Called on successful payment | | className | string | No | CSS class applied to the <iframe> |

The iframe starts at minHeight: 560px and auto-resizes via RESIZE postMessage events.


Usage Examples

Vanilla JS / TypeScript

import { pay } from '@palpluss/paylink'

document.getElementById('pay-btn')!.addEventListener('click', async () => {
  try {
    const { txId, amount } = await pay('abc-123')
    window.location.href = `/thank-you?ref=${txId}&amount=${amount}`
  } catch {
    // user closed the modal — no action needed
  }
})

React — modal trigger

import { pay } from '@palpluss/paylink'

export function CheckoutButton({ paylinkId }: { paylinkId: string }) {
  async function handleClick() {
    try {
      const result = await pay(paylinkId)
      console.log('Paid', result.amount, 'KES — ref:', result.txId)
    } catch {
      // modal dismissed
    }
  }

  return <button onClick={handleClick}>Pay with M-PESA</button>
}

React — inline embed

Use @palpluss/paylink/react when you want the payment form embedded directly in your page layout instead of a floating modal.

import { PalplussPayment } from '@palpluss/paylink/react'

export function CheckoutPage() {
  function handleSuccess({ txId, amount }: { txId: string; amount: number }) {
    console.log(`Payment complete — ${amount} KES, ref: ${txId}`)
  }

  return (
    <div className="checkout">
      <h1>Complete your payment</h1>
      <PalplussPayment id="abc-123" onSuccess={handleSuccess} />
    </div>
  )
}

CDN script tag

No build step required. Drop this into any HTML page:

<script src="https://cdn.palpluss.com/paylink.min.js"></script>

<button onclick="Palpluss.pay('abc-123').then(r => alert('Paid! Ref: ' + r.txId))">
  Pay with M-PESA
</button>

The script sets window.Palpluss — everything available on the Palpluss global:

Palpluss.pay('abc-123')
  .then(result => console.log(result))
  .catch(() => console.log('cancelled'))

TypeScript Types

import type { PaymentResult, PayOptions, IframeEvent } from '@palpluss/paylink'

type PaymentResult = {
  txId:   string   // transaction reference
  amount: number   // amount paid in KES
  phone:  string   // M-PESA number used
}

type PayOptions = {
  onSuccess?: (data: PaymentResult) => void
  onClose?:   () => void
}

// postMessage events sent by the embedded iframe
type IframeEvent =
  | { type: 'RESIZE';          height: number }
  | { type: 'PAYMENT_SUCCESS'; txId: string; amount: number; phone: string }

How the Modal Works Internally

When pay() is called:

  1. Overlay — a position: fixed; inset: 0 div with a semi-transparent backdrop is appended to document.body. z-index is set to 2147483647 (the maximum) so it sits above everything.
  2. Card — a centered white card (max-width: 860px) holds the close button and the iframe.
  3. Iframe — src is https://link.palpluss.com/{id}?embed=1. The ?embed=1 query param tells the Palpluss page it is running inside an SDK modal.
  4. Body scroll lockdocument.body.style.overflow = 'hidden' while the modal is open, restored on cleanup.
  5. postMessage listener — listens for two event types from the iframe origin:
    • RESIZE — adjusts iframe.style.height for seamless auto-height
    • PAYMENT_SUCCESS — extracts { txId, amount, phone }, calls onSuccess, removes the modal, resolves the Promise
  6. Close handlers — the modal closes (and the Promise rejects) on:
    • Clicking the button
    • Clicking outside the card on the backdrop
    • Pressing Escape
  7. Cleanup — removes the overlay from the DOM, restores scroll, removes all event listeners.

Relation to @palpluss/sdk

| Package | Runtime | Who uses it | What it does | |---|---|---|---| | @palpluss/sdk | Node.js | Backend developers | Server-side API calls — create paylinks, STK push, webhooks | | @palpluss/paylink | Browser | Frontend developers | Embed a payment link modal or inline iframe on any site |

These two packages are completely independent. A typical full-stack integration uses both:

Backend (Node.js)             Frontend (Browser)
──────────────────            ──────────────────
@palpluss/sdk                 @palpluss/paylink
  └─ createPaylink()   ──►      └─ pay(id)
  └─ handleWebhook()   ◄──            resolves on success

License

MIT