One runtime per page
Every widget on a page shares a single Web Worker and a single Python runtime. Ten editors cost one ~6MB download, not ten.
See two editors share a worker →A code editor that actually runs the code it shows, as one custom element. No backend, no iframe, no sign-up — it all happens in the reader's own browser. Type in the box and press Run.
Python · JavaScript · TypeScript · Java
Real CPython 3.14 via Pyodide — full standard library,
input(), tracebacks, numpy on demand — plus
the browser's own JavaScript engine, TypeScript with its types
stripped, and a documented subset of Java 25 compiled right in the
page. Each language loads only on the pages that use it.
That snippet blocks on input() — the program waits for you,
the way a terminal does. No cross-origin isolation required.
Every widget on a page shares a single Web Worker and a single Python runtime. Ten editors cost one ~6MB download, not ten.
See two editors share a worker →
A widget can hold a whole small project — flat modules, packages
with __init__.py, data files you open().
Tracebacks name the real file and line.
Python runs in a Worker, so while True: is a stoppable
mistake rather than a dead tab.
A subset of Java 25 — compact source files, methods, arrays,
strings — with javac-style errors and Java stack
traces. No JVM, no server, one small chunk.
Edits persist in IndexedDB, and soft navigation keeps the runtime warm between pages — the first run on a new lesson takes milliseconds, not seconds.
Walk between two lessons →Each language loads only when a widget needs it. These are the downloads once a reader presses Run, with the CDN build: one-widget pages loaded in a browser, each file gzipped, and CDN files as the CDN sent them.
| Page uses | code-playpad (gzip) | Also fetched from a CDN at run time | 0.3.0 (gzip) |
|---|---|---|---|
| Python | 166.3 KB | Pyodide, about 6.0 MB (a 3.3 MB wasm file and a 2.4 MB standard library) | 165.8 KB |
| JavaScript | 180.4 KB | nothing | 179.9 KB |
| TypeScript | 227.3 KB (with the 46.9 KB transform, since 0.5.2) | nothing | 179.9 KB |
| Java | 277.4 KB | nothing | 216.4 KB |
| Java, with collections | 372.5 KB | nothing | 233.2 KB |
| All four | 476.9 KB | Pyodide | 273.9 KB |
@codemirror/lang-java if you install it.
One script tag. CodeMirror is bundled; Python is fetched at runtime.
<script type="module"
src="https://cdn.jsdelivr.net/npm/code-playpad@0.8.0/dist/standalone.js"></script>
<code-playpad height="180">
print("hello from a CDN")
</code-playpad>
Or install it and use the modular build, with CodeMirror as a peer dependency so you never end up with two copies:
npm install code-playpad
React wrapper included — see it here. Works in plain HTML, Astro, Next.js, and anything else that can render an element.