What works in Nodepod

Nodepod is the browser-based Node.js runtime behind Codevre's terminal. This page covers what it supports, what it can't do, and how to work within browser limits.

Last updated 4 min read
On this page

Nodepod (opens in a new tab) runs Node.js programs inside a web page. It isn't a VM or a WebAssembly build of Node. It reimplements Node's APIs in JavaScript on top of an in-memory file system, runs processes as Web Workers, and serves HTTP servers through a service worker. In Codevre it runs on preview.codevre.dev, separate from the editor.

Node core modules with full implementations:

fs, path, events, stream, buffer, process, http, https, net, crypto, zlib, url, querystring, util, os, tty, child_process, assert, readline, module, timers, string_decoder, perf_hooks, constants, punycode

npm: npm install fetches from the public registry, resolves versions and checks package integrity, then installs into node_modules. npm run, npx and package.json scripts work. Installed packages are cached on your device, so reinstalling is fast.

Child processes: exec, execSync, spawn and fork work. Each process is a Web Worker.

HTTP servers: http.createServer and frameworks such as Express, Hono and Elysia listen on virtual ports. Codevre opens a Browser tab when they start. WebSockets to your server are bridged.

Tools: esbuild (as WebAssembly) and other pure-JS tools such as TypeScript's tsc, Prettier and most linters. Dev servers such as Vite may run, but are heavier in the browser.

Shell: a bash-like shell with pipes, redirects, variables, && and the common file commands.

Git: a built-in implementation. See Git and Source Control.

Some things simply don't exist inside a browser:

Not availableWhyUse instead
Native addons (.node files), node-gyp buildsThe browser can't load native binariesPure-JS packages
sharp, canvas (node-canvas)NativeBrowser <canvas> in the preview, jimp
sqlite3, better-sqlite3Nativesql.js, or JSON files
bcryptNativebcryptjs
puppeteer, playwrightNeed a real browser binaryTest in the preview
Python, Ruby, Go, Docker, system packagesNo OS to run them onJavaScript tools
Global installs (npm i -g)No system-wide install locationnpx, or local devDependencies
Raw TCP/UDP sockets, dgram, tls serversBrowsers only allow fetch and WebSocketsHTTP APIs

Modules that exist only as stubs: dns, worker_threads, vm, v8, tls, dgram, cluster, http2, inspector, domain, diagnostics_channel and async_hooks. Code can import them, but they don't do real work. For example, a BroadcastChannel from worker_threads is a no-op.

Networking from your code goes through the browser's networking. Outgoing requests from Node code (fetch, https.get) use Nodepod's proxying, and browser rules such as CORS can still apply. Some APIs block requests that come from a browser.

Performance: big installs and heavy builds run slower than on a native machine and use your device's memory. Very large projects, or many terminals running servers at once, can make the tab sluggish.

  • Your project lives in the workspace folder. pwd in a new terminal shows it; $CODEVRE_PROJECT_ROOT holds it.
  • / is Nodepod's own root, with /tmp, /dev, /home and /usr/local/bin. Don't write project paths as /file.js. Use paths relative to the project, or path.join(__dirname, …).
  • The file system lives in the page. Save to Codevre (Ctrl+S) keeps your project.
  • node_modules, .npm and .cache aren't saved. They're rebuilt from package.json when you reopen the project, using the cache on your device.
  • Running processes don't survive a reload or a runtime restart.
  • Caches (packages, node_modules snapshots, compiled modules) are stored in IndexedDB and, where available, the Origin Private File System. They can grow to several gigabytes; snapshots older than seven days are removed. Clearing site data for preview.codevre.dev frees the space.
  • Prefer no-build front ends served by localhost:codevre: index.html, style.css, script.js, with libraries from esm.sh or jsDelivr.
  • When you need bundling, use esbuild from a small build.js. esbuild in Nodepod treats imports it can't resolve as external. A page error like Dynamic require of "./x.js" is not supported means an import path is wrong.
  • For servers, use plain http or Express on port 3000 and send Cache-Control: no-store.
  • Restart a server after editing its code, or run it with a watcher (node --watch).

Codevre runs a custom build of Nodepod (@scelar/nodepod, loaded from preview.codevre.dev/nodepod/). It's mostly the same as upstream. Differences:

  • Git: UTF-8- and binary-safe clone, push and pull; push that records the commits it creates under GitHub's hashes; push that rejects non-fast-forward updates; pull that refuses to overwrite local changes or diverged history unless forced; and sparse-checkout.
  • Credentials: Git authentication is passed to individual Git commands by the IDE, never through the environment.
  • IDE integration: the vre and gh commands, server-ready events for Browser tabs, and DevTools for server previews.

For Nodepod's own documentation, API and source, see the Nodepod repository (opens in a new tab).

Docs