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 usestripe-pwa-elementsinstead.
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).
``
Unified payment form supporting multiple payment methods.
``
Express Checkout with Apple Pay, Google Pay, Link, and more.
``
(Beta) Payment Request API button (Apple Pay / Google Pay).
``
Address collection form with autocomplete.
``
Email collection with Stripe Link one-click checkout.
``
Currency selection component.
``
Modal wrapper for payment components.
``
Combined Card Element with Modal wrapper.
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:
- Card Element (dynamic) — JavaScript-driven component creation
- Card Element (static) — Declarative HTML markup
- Payment Element — Unified payment form
- Link Authentication — Email + Link checkout
- Address Element — Address collection
- Express Checkout — Apple Pay, Google Pay, etc.
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. SetSTRIPE_E2E_PORTonly if the demo API allows that origin too. - To use an already installed Chromium, set
PLAYWRIGHT_BROWSERS_PATH, or pointSTRIPE_E2E_CHROMIUM_PATHat 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
Recommended Tools
Try a different keyword or remove a filter.
Install
npx skillfish add hideokamoto/stripe-pwa-elements