HS

hideokamoto/stripe-pwa-elements

Developer tools
5 stars Quality 66 Trend 27MIT

Framework-agnostic Stripe payment components built with Web Components. Works with any web framework — React, Vue, Angular, Svelte, or plain HTML.

Overview

Framework-agnostic Stripe payment components built with Web Components. Works with any web framework — React, Vue, Angular, Svelte, or plain HTML. The current npm package is (this repo). The old package @stripe-elements/stripe-elements (v2.0.2) is deprecated and superseded — please use stripe-pwa-elements instead. Open the live demo in CodeSandbox (Stripe test mode, no setup or API keys needed) before installing anything. The demo covers: - — card number / expiry / CVC with a PaymentIntent confirm flow - — billing address form - — Apple Pay / Google Pay / Link (device-dependent) There is no demo yet. See examples/codesandbox for details. This library powers the Web implementation of @capacitor-community/stripe, which receives 4,000+ weekly downloads. If you use Capacitor for cross-platform apps, stripe-pwa-elements handles all Stripe UI on the web layer. Add a reciprocal link in the capacitor-community/stripe README pointing back to this package.

README

stripe-pwa-elements

Framework-agnostic Stripe payment components built with Web Components. Works with any web framework — React, Vue, Angular, Svelte, or plain HTML.

Note: The current npm package is stripe-pwa-elements (this repo). The old package @stripe-elements/stripe-elements (v2.0.2) is deprecated and superseded — please use stripe-pwa-elements instead.

Try it first

Open the live demo in CodeSandbox (Stripe test mode, no setup or API keys needed) before installing anything. The demo covers:

  • `` — card number / expiry / CVC with a PaymentIntent confirm flow
  • `` — billing address form
  • `` — Apple Pay / Google Pay / Link (device-dependent)

There is no `` demo yet. See examples/codesandbox for details.

Used in production

This library powers the Web implementation of @capacitor-community/stripe, which receives 4,000+ weekly downloads. If you use Capacitor for cross-platform apps, stripe-pwa-elements handles all Stripe UI on the web layer.

Manual follow-up (external repo): Add a reciprocal link in the capacitor-community/stripe README pointing back to this package.

Why stripe-pwa-elements?

Integrating Stripe from scratch requires wiring up several moving parts. This library collapses all of that into a single HTML element.

Before — raw @stripe/stripe-js (≈ 40 lines)


Pay

After — stripe-pwa-elements (≈ 5 lines)


<stripe-payment-element
  publishable-key="pk_test_xxxxx"
  intent-client-secret="pi_xxxxx_secret_xxxxx"
>

The component emits a defaultFormSubmitResult event when the payment completes, so you can react to success or failure without writing any Stripe boilerplate.

Value props

  • Framework-agnostic — Standard Web Components: drop into React, Vue, Angular, Svelte, or plain HTML with no adapter needed.
  • No build step — one CDN line — Load via `

### ES Module

```javascript
import { defineCustomElements } from 'stripe-pwa-elements/loader';
defineCustomElements();

Bundlers (Vite, webpack, Capacitor)

When using a bundler — including Capacitor apps built with Vite — import the components you need directly from the custom-elements build. Each module auto-registers its element on import, so no defineCustomElements() call is needed:

import 'stripe-pwa-elements/dist/components/stripe-payment-element';

This avoids the runtime dynamic import the lazy loader relies on, which can fail with Failed to fetch dynamically imported module under Vite. See the Bundler Integration guide for Vite/webpack/Rollup and Capacitor setup examples.

Components

``

Stripe Card form with split fields (card number, expiry, CVC).

Documentation

``

Unified payment form supporting multiple payment methods.

Documentation

``

Express Checkout with Apple Pay, Google Pay, Link, and more.

Documentation

``

(Beta) Payment Request API button (Apple Pay / Google Pay).

Documentation

``

Address collection form with autocomplete.

Documentation

``

Email collection with Stripe Link one-click checkout.

Documentation

``

Currency selection component.

Documentation

``

Modal wrapper for payment components.

Documentation

``

Combined Card Element with Modal wrapper.

Documentation

Quick Start

HTML

<stripe-card-element
  publishable-key="pk_test_xxxxx"
  intent-client-secret="pi_xxxxx_secret_xxxxx"
>

React

import { defineCustomElements } from 'stripe-pwa-elements/loader';

defineCustomElements();

function PaymentForm() {
  const handleFormSubmit = (e) => {
    const { stripe, cardNumber } = e.detail;
    stripe.createPaymentMethod({ type: 'card', card: cardNumber });
  };

  return (
    <stripe-card-element
      publishable-key="pk_test_xxxxx"
      intent-client-secret="pi_xxxxx_secret_xxxxx"
      onFormSubmit={handleFormSubmit}
    />
  );
}

Vue


  <stripe-card-element
    publishable-key="pk_test_xxxxx"
    intent-client-secret="pi_xxxxx_secret_xxxxx"
    @formSubmit="handleFormSubmit"
  />

Use with AI assistants

The documentation site publishes machine-readable plain-text files that AI coding assistants (Claude Code, Cursor, GitHub Copilot, etc.) can use to answer questions about this library without hallucinating outdated API details.

File Purpose
/llms.txt Index — links to the full and compact documentation sets
/llms-full.txt Full API reference for all components
/llms-small.txt Compact version with non-essential content removed

These files are generated automatically from the documentation source at build time using the starlight-llms-txt plugin and always reflect the latest published docs.

Examples

See the example/ directory for complete working examples:

Use with coding agents (Agent Skill)

This repo ships an Agent Skill that teaches coding agents how to integrate stripe-pwa-elements correctly — picking the right component, wiring the publishable key + client secret, handling the submit/confirm flow, and asking before anything that changes your Stripe account. The skill lives in plugins/stripe-pwa-elements/skills/stripe-pwa-elements/.

Install it with the skills CLI:

npx skills add hideokamoto/stripe-pwa-elements

Or, in Claude Code, install it as a plugin:

/plugin marketplace add hideokamoto/stripe-pwa-elements
/plugin install stripe-pwa-elements@stripe-pwa-elements

Once installed in Claude Code, the skill activates automatically when Claude detects you are working with the library, or you can invoke it explicitly with /stripe-pwa-elements:stripe-pwa-elements.

The documentation site also serves the skill over HTTP, built from the same file:

URL Purpose
/skill.md The skill’s SKILL.md
/.well-known/agent-skills/index.json Discovery index (Agent Skills Discovery RFC, draft v0.2.0) with a SHA-256 digest per skill
/.well-known/agent-skills/stripe-pwa-elements/SKILL.md The skill at the path the discovery index points to

Contribution

Getting Started

npm install
npm start

To build the component for production, run:

npm run build

To run the unit tests for the components, run:

npm test

Real-browser checks against Stripe test mode

e2e/stripe/ holds Playwright checks that drive the built components in Chromium against the real Stripe.js, in Stripe test mode. They use the docs site’s demo API (https://stripe-pwa-elements-docs.wp-kyoto.workers.dev/api) for the pk_test_ key and for new PaymentIntents, so no keys are needed. They need network access to js.stripe.com and to that API, so they are not part of CI.

pnpm run build                            # the harness serves www/build
pnpm exec playwright install chromium     # once, if Playwright has no Chromium yet
pnpm run test:e2e:stripe
  • The harness is served on http://localhost:4321, an origin the demo API allows. Set STRIPE_E2E_PORT only if the demo API allows that origin too.
  • To use an already installed Chromium, set PLAYWRIGHT_BROWSERS_PATH, or point STRIPE_E2E_CHROMIUM_PATH at the executable.
  • Traces and screenshots of failed tests go to test-reports/stripe-e2e/.
  • Type-check the suite with pnpm exec tsc -p e2e/stripe/tsconfig.json.

To add a check: add a scenario to e2e/stripe/*.pw.ts using PaymentSheetHarness (e2e/stripe/support/payment-sheet.ts) and the demo API helpers (e2e/stripe/support/demo-api.ts). Element options and attributes go through harness.mount({ publishableKey, clientSecret, options, attributes }). To check what Stripe received or saved (confirm request params, billing details on the PaymentMethod, shipping on the PaymentIntent), use e2e/stripe/support/stripe-api.ts, as payment-sheet-billing.pw.ts does. For a different page, add an HTML file to e2e/stripe/pages/ that exposes the same window.harness contract and open it with harness.goto('/e2e/.html').

Keep the Agent Skill up to date

When you add, rename or remove a component, or change its props, events, methods or how it is loaded, update the Agent Skill in plugins/stripe-pwa-elements/skills/stripe-pwa-elements/ in the same pull request. src/agent-skill.unit.spec.ts fails when the skill’s component tags, CDN bundle path or i18n languages no longer match the code.

Security & PCI DSS SAQ-A

Card data never passes through this library’s DOM, JavaScript state, or network requests. All sensitive input fields (card number, expiry, CVC) are rendered inside Stripe-hosted iframes, meaning your page never has access to raw card data. This architecture keeps integrations eligible for the lightest PCI DSS self-assessment questionnaire: SAQ-A.

How iframe isolation works

Your page (your domain)
┌─────────────────────────────────────────────────────────┐
│                                    │
│  ┌───────────────────────────────────────────────────┐  │
│  │           │  │
│  │  ┌─────────────────────────────────────────────┐  │  │
│  │  │  Card number  [____ ____ ____ ____]          │  │  │
│  │  │  Expiry       [MM/YY]  CVC  [___]            │  │  │
│  │  │                                              │  │  │
│  │  │  (Stripe's origin — cross-origin boundary)   │  │  │
│  │  └─────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  Your JS can call stripe.confirmPayment() but           │
│  CANNOT read card values from the iframe.               │
└─────────────────────────────────────────────────────────┘
  • The browser’s same-origin policy prevents any JavaScript on your page from reading input values inside Stripe’s iframe.
  • Card data travels directly from the iframe to Stripe’s servers over TLS — it never touches your application server.
  • This library only manages the mounting, styling, and event wiring of those iframes; it does not alter Stripe’s security model.

For a complete explanation see Stripe’s SAQ-A documentation.

For the vulnerability reporting channel and supply-chain notes (npm provenance), see SECURITY.md.


Sponsors

If stripe-pwa-elements saves you time, please consider sponsoring the lead maintainer:


Public API & TypeScript types

All user-facing TypeScript types are exported directly from the package root. Import them using the package name:

import type {
  FormSubmitEvent,
  FormSubmitHandler,
  StripeLoadedEvent,
  StripeDidLoadedHandler,
  ProgressStatus,
  IntentType,
  InitStripeOptions,
  LinkAuthenticationElementChangeEvent,
  LinkAuthenticationElementChangeHandler,
  CurrencySelectorChangeEvent,
  CurrencySelectorChangeHandler,
  DefaultFormSubmitResult,
} from 'stripe-pwa-elements';

The custom-elements entry stripe-pwa-elements/dist/components/ is a supported import path for bundler-based setups (see Bundlers above). However, do not import from internal paths such as dist/types/interfaces. Those paths are implementation details and are not part of the public API — they may change without notice across any release.

Semver policy

All types exported from the package root (stripe-pwa-elements) are considered public API and follow Semantic Versioning. Within the ^3.0.0 range:

  • No breaking changes will be made to the shape of any publicly exported type.
  • New optional fields may be added to event objects without a major bump.
  • Removals or renames of exported types always require a new major version.

Maintainers

Maintainer GitHub Social
Hidetaka Okamoto hideokamoto @hide__dev
Masaki Hirano contiki9 @maki_saki
Masahiko Sakakibara rdlabo @rdlabo

License

MIT

View the full README on GitHub

Recommended Tools

Try a different keyword or remove a filter.

Install

npx skillfish add hideokamoto/stripe-pwa-elements
New to MCP? Start with the mcpskill.org guide →