From cppjs
Guides developers to wrap C++ libraries like libsodium, FFTW, OpenCV as reusable cpp.js packages installable via pnpm add, using scaffold script, CMake builds, and upstream versioning.
npx claudepluginhub bugra9/cpp.js --plugin cppjsThis skill uses the workspace's default tool permissions.
Walk the user through wrapping a C++ library as a `cppjs-package-*` family that other projects can `pnpm add`.
Integrates cpp.js into existing JavaScript/TypeScript/React Native projects by detecting framework/bundler (Next.js, Vite, Webpack, etc.) and applying matching playbook for plugins, config, and init.
Writes idiomatic modern C++ code with RAII, smart pointers, STL algorithms, templates, move semantics, and performance optimization. For refactoring, memory safety, complex patterns.
Writes idiomatic modern C++ code using RAII, smart pointers, STL algorithms, templates, move semantics, and performance optimizations. Provides CMake, tests, and benchmarks.
Share bugs, ideas, or general feedback.
Walk the user through wrapping a C++ library as a cppjs-package-* family that other projects can pnpm add.
Does this package extend or affect GDAL (or another package already in
the cpp.js monorepo's transitive dep graph)?
│
├─ YES → Add directly to the cpp.js repo (cppjs-packages/cppjs-package-<name>/).
│ Use the @cpp.js/* npm scope.
│ This requires a PR to https://github.com/bugra9/cpp.js
│
└─ NO → Author it outside this repo:
1. Strongly encourage the cppjs-community GitHub org. Help the
user file a "transfer to cppjs-community when ready" plan.
2. They can also keep it in their own org. In that case:
- npm name MUST be unscoped: `cppjs-package-<name>`
- NOT `@user/cppjs-package-<name>`, NOT `@cpp.js/...`
The unscoped naming pattern lets cpp.js's plugin discovery find
packages by name regardless of org.
The cpp.js repo ships a scaffold script:
node scripts/scaffold-package.js <name> [--scope ""] [--license MIT] [--lib <name>]
The script copies cppjs-packages/cppjs-package-zlib/ (smallest reference) and rewrites:
cppjs-package-zlib → cppjs-package-<name> (filenames + content).package.json: name, version: 0.1.0, nativeVersion: "", license, keywords, drop zlib workspace deps.libz.a → lib<name>.a, z.xcframework → <name>.xcframework).For community / user-org packages: --scope "" (unscoped npm name).
Skips build artifacts (dist/, .cppjs/, node_modules/, *.xcframework) so the user gets a clean starting tree.
Edit each sub-arch's cppjs.build.js:
getSource(): download / clone / copy the upstream source. Use state.config.paths.build for staging.prepare(): cmake configure step (or ./configure for autotools).build(): cmake build / make install.Build system priority:
CMakeLists.txt. Easiest cross-platform../configure && make) for libraries without CMake. Set state.config.build.buildType = 'configure'. See cppjs-package-openssl-* for reference.Always use the latest stable upstream version. Resolution order:
The repo's helper does all three:
pnpm run check:native -- --update
This auto-bumps nativeVersion in every affected package.json (or writes it for the first time on a fresh package).
If the library links against zlib, openssl, etc., add them to each sub-arch's package.json dependencies:
"dependencies": {
"@cpp.js/package-zlib-wasm": "workspace:^",
"@cpp.js/package-openssl-wasm": "workspace:^"
}
Same for -android, -ios. pnpm derives topological build order from this; without it, the linker fails with "undefined symbol".
pnpm install
pnpm --filter='@cpp.js/package-<name>*' run build
Wasm + Android build on Linux/macOS. iOS only on macOS.
Per sub-arch: package.json, cppjs.config.js, cppjs.build.js, README.md, LICENSE (upstream's), .npmignore. iOS adds cppjs-package-<name>.podspec with EXCLUDED_ARCHS[sdk=iphonesimulator*] = x86_64.
The scaffold script gets all of these from the zlib template, but the user must:
LICENSE content with upstream's actual license..npmignore excludes .cppjs/, source tarballs, intermediates — but keeps dist/prebuilt/ (consumers need it).Only do this if the package fits "GDAL-affecting" criteria:
cppjs-samples/cppjs-playground-*).pnpm run e2e:dev && pnpm run e2e:prod must pass.cppjs-package-<name>/ family.For community / user-org packages, skip e2e. Standalone build success is enough; the user's own consumer project tests it.
@cpp.js/* scope without checking the GDAL-affect routing.nativeVersion pinning.EXCLUDED_ARCHS[sdk=iphonesimulator*] = x86_64 on the iOS podspec.Full playbook: https://github.com/bugra9/cpp.js/blob/main/docs/playbooks/new-package.md
Scaffold script: https://github.com/bugra9/cpp.js/blob/main/scripts/scaffold-package.js
Canonical small example: cppjs-packages/cppjs-package-zlib/
Big aggregator example: cppjs-packages/cppjs-package-gdal/
autotools example: cppjs-packages/cppjs-package-openssl/