• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
alexanerstalbrandklarna

alexanerstalbrandklarna

JPM-setup

How to limit usage to one iframe of initializing Klarna Web SDK
Public
Like
JPM-setup
Home
Code
8
.claude
1
frontend
3
shared
1
.vtignore
AGENTS.md
CLAUDE.md
deno.json
H
main.ts
Environment variables
Branches
1
Pull requests
Remixes
1
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
CLAUDE.md
Code
/
CLAUDE.md
Search
2/24/2026
Viewing readonly version of main branch: v47
View latest version
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a Val Town project — a Klarna payment integration prototype demonstrating iframe-based payment flows for the JPM (J.P. Morgan) partnership. It runs on the Val Town platform (Deno serverless runtime, not Node.js).

Running the Project

This project is deployed and run via Val Town. Locally, use the vt CLI:

vt dev # Start local dev server vt push # Deploy to Val Town vt pull # Pull latest from Val Town

The project has a .vt/state.json that tracks the Val Town project ID and branch.

Architecture

The app uses a three-context iframe architecture for Klarna payment integration:

  1. main.ts — HTTP request handler (Val Town entry point). Serves static files from frontend/ and shared/ using Val Town's serveFile/readFile utilities.

  2. frontend/index.html — First-party merchant page. Orchestrates payment flow by:

    • Embedding button-iframe.html for the Klarna pay button
    • Dynamically creating a popup overlay with popup-iframe.html when payment is initiated
    • Routing postMessage events between the two iframes
  3. frontend/button-iframe.html — Third-party iframe containing the Klarna SDK payment button. On click, sends show-popup message to parent.

  4. frontend/popup-iframe.html — Third-party iframe for the Klarna payment flow. Receives initiate-payment from parent, runs klarna.Payment.initiate(), and sends back payment-complete or payment-abort.

  5. shared/types.ts — TypeScript type definitions for all postMessage payloads (ShowPopupMessage, InitiatePaymentMessage, PaymentCompleteMessage, PaymentAbortMessage, ClosePopupMessage) plus type guard functions.

PostMessage Flow

button-iframe  →  show-popup        →  index.html (parent)
index.html     →  initiate-payment  →  popup-iframe
popup-iframe   →  popup-ready       →  index.html
popup-iframe   →  payment-complete  →  index.html
popup-iframe   →  payment-abort     →  index.html

Val Town Platform Constraints

  • Runtime is Deno, not Node.js — use Deno.env.get() for env vars, not process.env
  • Use https://esm.sh for npm imports (works in both server and browser)
  • Code in shared/ must work in both frontend and backend — cannot use Deno namespace there
  • Entry point exports a default async function: export default async function(req: Request)
  • Use Response.redirect workaround: new Response(null, { status: 302, headers: { Location: url } })
  • Do NOT use Deno KV, alert(), prompt(), or confirm()
  • Imports use URL-based specifiers (e.g., https://esm.town/v/std/utils@85-main/index.ts)

Klarna SDK

Both iframes initialize the Klarna Web SDK v2 from https://js.playground.klarna.com/web-sdk/v2/klarna.mjs using test credentials. The SDK is configured with products: ["PAYMENT"].

Styling

Uses TailwindCSS via twind CDN (https://cdn.twind.style). When using React, pin all dependencies to react@18.2.0.

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
AboutAlternativesPricingBlogNewsletterCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.