cpp.js — Runtime & Config API Reference
For AI agents and humans alike. Every option, every default, every constraint — in one place. If you're integrating cpp.js into a project, start with
init.md. If you're authoring acppjs.config.js, seecppjs-config.md.
cpp.js has two API surfaces that get confused often. Keep them straight:
| Surface | When | Authored by | Documented in |
|---|---|---|---|
initCppJs(opts) | Runtime — at the moment your app calls into Wasm | Every consumer | init.md |
cppjs.config.js | Build-time — read by the cppjs build CLI | Every consumer | cppjs-config.md |
cppjs.build.js | Build-time — only inside cppjs-package-* source folders | Package authors only | cppjs-build.md |
Cross-cutting topics:
filesystem.md— How files persist (or don't) across browser, Node, and edge runtimes. Covers OPFS, memfs, theuseWorkerrequirement, and the auto-fallback chain.threading.md— Single-thread vs multi-thread Wasm, the COOP/COEP requirement, whyuseWorkeris a separate axis from threading, and what edge runtimes can't do.
C++ binding & build authoring:
cpp-binding-rules.md— Rules for writing C++ that cpp.js can auto-bind (no raw pointers, C++11+, wrapper pattern, JSPI advanced).swig-escape.md— Manual SWIG.ifiles when auto-generation isn't enough.build-state.md—stateandtargetobject shapes passed tocppjs.build.jshooks; full inventory of 20 built-in build targets.overrides.md— Catalog of 20 override mechanisms ordered least → most invasive.troubleshooting.md— Common errors mapped to the right override; tribal-knowledge gotchas from real packages.performance.md— Default Emscripten + CMake flags reference; what's safe to override and what to leave alone.lifecycle-and-types.md— Why JS-sidem.delete()isn't a thing in cpp.js + TypeScript.d.tsnotes.
The 30-second mental model
┌─────────────────────────────────────────────────────────────┐
│ Build time: cppjs build CLI │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ cppjs.config.js │ + │ cppjs.build.js │ │
│ │ (consumer-side) │ │ (package author │ │
│ │ deps, paths, flags │ │ only — wraps a │ │
│ │ runtime: st|mt │ │ C++ library) │ │
│ └────────────────────┘ └────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ Emcc / NDK / Xcode produces .wasm / .a / .xcframework │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Runtime: your app │
│ ┌────────────────────────────────────────────────────────┐│
│ │ const m = await initCppJs({ ││
│ │ useWorker: true, // for OPFS persistent storage ││
│ │ fs: { opfs: true }, // browser default ││
│ │ env: { ... }, ││
│ │ onRuntimeInitialized: (m) => {...}, ││
│ │ }) ││
│ │ // m.FS, m.toVector, m.autoMountFiles, ... ││
│ └────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Common pitfalls (read these even if you skip the rest)
cppjs.config.jsis NOT runtime config. It's read once by thecppjs buildCLI. PuttinguseWorker: truehere does nothing — that's a runtime option forinitCppJs(opts).- OPFS persistent storage in browser requires
useWorker: true. OPFS API is only exposed in Worker scope. Mounting/opfs/...from the main thread throws. runtime: 'mt'in production silently fails without COOP/COEP headers. Dev plugins inject them; prod hosts (Vercel, Netlify, nginx, Cloudflare Pages, …) need explicit configuration.- Edge runtimes (Cloudflare Workers, Deno Deploy, Vercel Edge) don't support Web Workers. That means no
useWorker, no OPFS, no multithread — only single-thread + in-memory fs. paths.nativeis an array. Not a string.fs.existsSync(paths.native)is a bug.
See also
- ADRs that constrain these APIs: ADR-0003 (function-typed env values).
- High-level integration playbooks per framework:
docs/playbooks/integration/. - Codemap for source pointers:
docs/CODEMAP.md.