Get Next.js running inside BrowserPod: install completes, dev server starts, portal opens, page loads.
--ignore-scriptsrequired on all installs to preventSYS_GETSOCKOPThang from native binary postinstall scriptshandleExecvein the BrowserPod service worker is unreliable — usepod.run('node', [...])directlyBrowserPodProcess.then()returnsundefined— cannot chain.catch()- The inspector API (
node:inspector) is not implemented - Web Crypto
SecretKeyGenJobis not implemented (crypto.subtle.generateKeyfor AES keys fails) - BrowserPod CAN make outbound network requests (e.g. to npm registry)
Symptom: npm run dev echoed in terminal but portal never appeared.
Cause: npm run dev spawns child processes via handleExecve in the BrowserPod service worker, which is unreliable.
Fix: Added devCmd: 'node' and devArgs: ['node_modules/next/dist/bin/next', 'dev', '-H', '0.0.0.0', '-p', '3000'] to bypass npm entirely.
Result: Still hangs silently.
Symptom: Silent hang — suspected Next 16 defaulting to Turbopack (native Rust).
Attempt: Added --no-turbopack to devArgs.
Result: error: unknown option '--no-turbopack' — flag does not exist in Next 16. Removed.
Observation: Next's package.json was missing the esbuild-wasm and @rollup/wasm-node overrides present in all other recipes.
Fix: Added overrides to public/projects/next/package.json.
Result: No change to hang behaviour.
Test: import('@next/swc-wasm-nodejs') → swc ok
Symptom: Despite the package being installed, Next prints:
⚠ next-swc does not have native bindings for platform linux/wasm32.
Downloading swc package @next/swc-wasm-nodejs... to /.cache/next-swc
Then hangs on the download.
Cause: Next 16 looks for a native .node binary. The WASM package doesn't match what Next 16 expects — Next rejects the installed package and tries to download a fresh one. The download stalls (BrowserPod can make network requests but this particular download never completes).
Conclusion: Next 16 is SWC-only with no Babel fallback. Dead end.
Rationale: Next 14 still supports Babel as a fallback when babel.config.json is present. SWC is attempted first but gracefully falls back.
Files changed:
public/projects/next/package.json:next@14.2.29,react@18.3.1,react-dom@18.3.1, removed@next/swc-wasm-nodejspublic/projects/next/babel.config.jsonadded:{ "presets": ["next/babel"] }src/recipes.jsstack label updated
Rationale: Same approach that worked for Vite — use the programmatic API with diagnostic logging to find exactly where startup hangs.
Initial version:
process.env.NEXT_TELEMETRY_DISABLED = '1';
const next = (await import('next')).default;
const app = next({ dev: true, hostname: '0.0.0.0', port: 3000 });
await app.prepare();
http.createServer(app.getRequestHandler()).listen(3000, '0.0.0.0');Symptom:
TypeError: Inspector is not available (ERR_INSPECTOR_NOT_AVAILABLE)
Cause: Next's webpack compilation loads the node:inspector built-in which BrowserPod does not implement.
Fix: Patched Module._load in start-next.mjs to intercept inspector/node:inspector and return a stub object.
Result: Error resolved.
Symptom:
TypeError: SecretKeyGenJob is not a constructor
at generateKey (...)
at aesGenerateKey (...)
at SubtleCrypto.__g__
Cause: BrowserPod's Web Crypto implementation doesn't support AES key generation (crypto.subtle.generateKey). Next 14 uses this for cookie/session signing during startup.
Fix: Patched globalThis.crypto.subtle.generateKey and exportKey to catch failures and return stub key material (fixed 32-byte buffer from crypto.randomBytes(32)).
Result: Error resolved.
Symptom:
⚠ Trying to load next-swc for unsupported platforms linux/wasm32
Downloading swc package @next/swc-wasm-nodejs...
Then hangs.
Cause: @next/swc-wasm-nodejs was removed from package.json in step 5. Without it, Next falls back to downloading.
Fix: Added babel.config.json with { "presets": ["next/babel"] }. Next 14 detects this and disables SWC in favour of Babel.
Result: Next now prints:
Disabled SWC as replacement for Babel because of custom Babel configuration "babel.config.json"
No more download hang. SWC bypassed successfully.
Rationale: Next's webpack uses worker threads for compilation. Added config to disable build workers.
Result: No observable change — app.prepare() still completes successfully regardless.
Symptom: After startup succeeds and port 3000 binds, compiling / fails:
⨯ ./node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/getErrorByType.js
node:https:
Next's dev overlay imports node:https which webpack tries to bundle into the client-side JS — not valid in a browser context.
Consequence: fallback-build-manifest.json is never written → every page request returns 500.
Attempt A: resolve.alias with 'node:https': false etc.
Result: No effect — webpack doesn't honour resolve.alias: false for node: built-ins.
Attempt B: resolve.fallback with bare module names (https: false, http: false, etc.)
Result: No effect — webpack treats node:https as a different specifier from https.
Attempt C: resolve.fallback with both bare and node: prefixed names
Result: Still failing.
Rationale: Try intercepting node: prefixed imports at the NormalModuleFactory level, replacing with empty-module.js.
new webpack.NormalModuleReplacementPlugin(
/^node:/,
require.resolve('./empty-module.js')
)Result: No effect. Same node:https error and missing fallback-build-manifest.json.
Conclusion: webpack 5 handles node: prefixed modules before NormalModuleFactory.hooks.beforeResolve fires. NormalModuleReplacementPlugin never sees them.
Rationale: Previous alias attempts used false (which means "no polyfill, emit error"). Using an actual path to empty-module.js should make webpack substitute the empty module instead of erroring. The node-polyfill-webpack-plugin uses this exact pattern for node: prefixed modules.
const emptyModule = path.resolve(__dirname, 'empty-module.js');
const builtins = ['assert', 'async_hooks', 'buffer', ..., 'https', ...];
for (const name of builtins) {
config.resolve.alias[`node:${name}`] = emptyModule;
}Result: Pending test.
- Next starts, binds port 3000, portal opens
- Babel is used for server-side compilation (SWC bypassed)
- Client-side bundle compilation fails on
node:httpsin Next's dev overlay - All page requests return 500
- Patch
getErrorByType.jsinsidenode_modules/nextinstart-next.mjsbefore importing Next — replacerequire('node:https')with a no-op stub. Direct file mutation, guaranteed to work. - Alias the entire
react-dev-overlaycomponent chain to empty modules viaresolve.aliason full file paths (e.g.next/dist/client/components/react-dev-overlay/pages/hot-reloader-client)