npm playground is a small demo app that lets a user pick an npm package, write code against it, and execute that code inside a Cloudflare Dynamic Worker.
This is intentionally a demo, not a production app.
- Serves a simple browser UI from Worker static assets.
- Lets a user choose one of several built-in package examples or type any npm package name.
- Bundles the selected package together with the user's code at runtime using
@cloudflare/worker-bundler. - Runs that bundled code inside a Dynamic Worker with outbound network access disabled.
- Returns the execution result and captured console output back to the host Worker and then to the UI.
There are two main parts:
- The host Worker in
src/index.ts - The static UI in
public/
The host Worker handles /api/* routes and serves the UI assets for everything else.
When a user clicks Run code, the host Worker:
- Reads the selected package name, version, and editor contents.
- Builds a temporary in-memory project containing:
- the dynamic worker entry module
- the user's code
- a generated
package.jsonwith the chosen dependency
- Uses
createWorker()from@cloudflare/worker-bundlerto compile and bundle that project. - Loads the bundle through the Worker Loader binding.
- Calls a named RPC entrypoint on the Dynamic Worker to execute the code.
The Dynamic Worker does not talk back over HTTP. Instead, the host Worker calls a Playground RPC entrypoint directly and receives a structured object containing:
- success or failure
- captured console logs
- the serialized return value
- any execution error details
The Dynamic Worker is created with globalOutbound: null, which blocks outbound network access from the executed code.
That means user code can use the bundled npm dependency and the Worker runtime, but it cannot freely call the public Internet from inside the Dynamic Worker.
- This is a demo & vibe-coded
@cloudflare/worker-bundleris experimental.- Only one npm package is injected through the generated
package.jsonfor each run. - Returned values are serialized into UI-safe data, so not every complex runtime object will round-trip perfectly.
- This project currently favors simplicity and approachability over strict security hardening or production-grade tenancy controls.
Install dependencies:
npm installStart the app locally:
npx wrangler devIf you change bindings in wrangler.jsonc, regenerate Worker types:
npx wrangler typessrc/index.ts: host Worker API, runtime bundling, Dynamic Worker creation, and RPC executionpublic/index.html: app shellpublic/app.js: browser behaviorpublic/styles.css: UI stylingwrangler.jsonc: Worker config, assets binding, and Worker Loader binding