How to Build a Disposable npm Package Sandbox in the Browser
Sometimes the question is not “should we add this package?” It is “can I inspect it without turning my machine into the test environment?”
That comes up in internal tooling, package review flows, workshops, onboarding, and any other situation where you want a disposable Node environment for package experiments. The npm_package_tester demo searches npm, installs a package inside BrowserPod, runs a few follow-up commands, and throws the whole environment away with the tab.
Start with npm search instead of making people know the exact package name
The demo begins with registry search so the user does not need the exact package name before the sandbox is useful.
It queries npm’s search endpoint directly:
async function searchPackages(keyword, page = 0) {
const from = page * 20;
const response = await fetch(
`https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(keyword)}&size=20&from=${from}`
);
const data = await response.json();
searchState.totalResults = data.total || 0;
return data.objects || [];
}
The flow is simple:
- search by keyword
- pick a package from the result list
- run the package test inside the browser session
Boot BrowserPod once and reuse the terminal
The package sandbox only needs one pod for the session, so the demo boots BrowserPod once and reuses the same terminal:
async function initBrowserPod() {
const apiKey = import.meta.env.VITE_BP_APIKEY;
pod = await BrowserPod.boot({ apiKey });
pod.onPortal(({ url, port }) => {
log(`Portal available at: ${url}`, "success");
setServerInfo(`Portal: <a href="${url}" target="_blank">${url}</a>`);
});
const consoleElement = document.getElementById("console");
terminal = await pod.createDefaultTerminal(consoleElement);
return true;
}
Package inspection is a command-driven workflow. One reusable runtime is easier to work with than a fresh pod on every click.
Install into an isolated working directory
When the user clicks Test Package, the demo installs into /root/test inside the pod:
async function testPackage(packageName) {
const workDir = "/root/test";
await withTimeout(
pod.run("npm", ["install", packageName, "--no-update-notifier"], {
terminal: terminal,
cwd: workDir,
}),
60000
);
}
The install happens in the BrowserPod session, not on the host machine. Close the tab and the package, its dependencies, and the test environment disappear with it.
Run follow-up npm commands after install
After npm install, the demo runs a few follow-up commands:
await pod.run("npm", ["ls", packageName, "--no-update-notifier"], {
terminal: terminal,
cwd: workDir,
});
await pod.run("npm", ["fund", "--no-update-notifier"], {
terminal: terminal,
cwd: workDir,
});
It also attempts to run an audit step:
const auditOutput = await captureCommand("npm", [
"audit",
"--no-update-notifier",
]);
const auditJson = auditOutput.includes("{")
? auditOutput.substring(auditOutput.indexOf("{"))
: "{}";
The UI uses that output to show a small summary card next to the terminal output.
Keep the terminal and the app log separate
This demo uses two output surfaces:
- the BrowserPod terminal for command output
- a browser-side console panel for UI events and status messages
export function log(msg, type = "info") {
const consoleDiv = document.getElementById("app-console");
const entry = document.createElement("div");
entry.className = `console-entry ${type}`;
entry.innerHTML = `<span class="console-timestamp">[${now}]</span> ${msg}`;
consoleDiv.appendChild(entry);
}
Show the result in plain terms
After the commands finish, the demo updates a small results section:
function displayResults(packageName, auditData) {
const vulnCount = auditData.metadata?.vulnerabilities?.total || 0;
if (vulnCount === 0) {
securityHtml =
'<div class="result-item safe"><span class="result-label">✓ No vulnerabilities found</span></div>';
}
}
Where this fits
Use this for disposable package inspection, not for definitive package approval.
Examples:
- giving developers a sandbox for quick npm experiments
- building an internal package review tool
- teaching how installs and dependency trees behave
- letting someone inspect a package without changing their local machine
If you need deeper supply chain analysis, long-lived environments, or compatibility with native binaries, use a different setup. If you need a quick Node sandbox for npm commands that lives only as long as the browser session, this demo fits.