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

klarnapublic

JPM-setup

How to limit usage to one iframe of initializing Klarna Web SDK
Remix of alexanerstalbrandklarna/JPM-setup
Public
Like
JPM-setup
Home
Code
8
.claude
1
frontend
5
shared
1
.vtignore
AGENTS.md
CLAUDE.md
deno.json
H
main.ts
Environment variables
Branches
1
Pull requests
Remixes
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
…
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 single-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. Embeds a single <iframe> pointing to klarna-iframe.html. Listens for postMessage events to resize the iframe between button-size and fullscreen, and to display payment results.

  3. frontend/klarna-iframe.html — Third-party iframe containing both the Klarna SDK payment button and the payment flow. Has a transparent background so the merchant page shows through the SDK's overlay. On button click, tells the parent to expand to fullscreen, then initiates Payment.initiate() with ON_PAGE mode. On completion/abort, tells the parent to shrink back to button size.

  4. shared/types.ts — TypeScript type definitions for all postMessage payloads (ButtonReadyMessage, ExpandIframeMessage, ShrinkIframeMessage, PaymentCompleteMessage, PaymentAbortMessage) plus type guard functions.

PostMessage Flow (all iframe → parent)

klarna-iframe  →  button-ready       →  index.html (parent sizes iframe)
klarna-iframe  →  expand-iframe      →  index.html (parent goes fullscreen)
klarna-iframe  →  shrink-iframe      →  index.html (parent restores button size)
klarna-iframe  →  payment-complete   →  index.html (parent shows result)
klarna-iframe  →  payment-abort      →  index.html (parent shows result)

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

The iframe initializes 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"]. Payment is initiated with initiationMode: "ON_PAGE" so the SDK renders its overlay inside the fullscreen iframe rather than trying to open a popup (which would be blocked from within an iframe).

Styling

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

Get started with a template:
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
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.