# Platform Notes

> NumKong for JavaScript

### Browser and WASM

The npm package includes pre-built WASM modules under `wasm/`, one per SIMD capability and address width: `numkong-wasm32-serial`, `numkong-wasm32-v128`, `numkong-wasm32-v128relaxed`, and `numkong-wasm64-v128relaxed`.
The `numkong/wasm` entry validates two tiny probe modules on import and picks the best wasm32 capability the engine accepts, so Chrome, Firefox, and Node get Relaxed SIMD, Safari and iOS WebKit get strict SIMD128, and an engine without SIMD gets `serial`.
Each module is its own package subpath, like `numkong/wasm32-v128`, so a bundler splits them and the page fetches only the one it runs.
A page without a bundler maps those subpaths itself:

```html
<script type="importmap">
  {
    "imports": {
      "numkong/wasm32-serial": "https://cdn.jsdelivr.net/npm/numkong@8/wasm/numkong-wasm32-serial.js",
      "numkong/wasm32-v128": "https://cdn.jsdelivr.net/npm/numkong@8/wasm/numkong-wasm32-v128.js",
      "numkong/wasm32-v128relaxed": "https://cdn.jsdelivr.net/npm/numkong@8/wasm/numkong-wasm32-v128relaxed.js"
    }
  }
</script>
<script type="module">
  import { dot, euclidean } from 'https://cdn.jsdelivr.net/npm/numkong@8/wasm/numkong.js';

  const query = new Float32Array([1.0, 2.0, 3.0]);
  const doc = new Float32Array([4.0, 5.0, 6.0]);
  console.log(dot(query, doc));          // 32 — SIMD-accelerated, client-side
  console.log(euclidean(query, doc));    // 5.196...
</script>
```

For self-hosted WASM, download the entries and the modules from a [GitHub Release](https://github.com/ashvardanian/NumKong/releases), serve them from one directory, and point the same import map at it.
Each module finds its `.wasm` binary relative to its own URL.

The opt-in `numkong/wasm-extended` entry loads `numkong-wasm64-v128relaxed`, with Memory64, threads and Relaxed SIMD, where the engine validates them and the page is cross-origin isolated, and throws otherwise.
Node runs it from version 24, whose Memory64 takes 64-bit sizes, while the package and the minimal entry keep Node 22 as the floor:

```javascript
const numkong = await import("numkong/wasm-extended").catch(() => import("numkong/wasm"));
```

Or import the subpath from a bundler or Node.js (without the native addon):

```javascript
import { dot } from "numkong/wasm";
```

To build the modules in a checkout, the `wasm32_emscripten` preset makes one per `NUMKONG_MARCH`, both into `build_wasm32_emscripten/`, where `npm run build-browser` bundles the loader beside them:

```sh
source ~/emsdk/emsdk_env.sh
cmake --preset wasm32_emscripten && cmake --build --preset wasm32_emscripten
cmake --preset wasm32_emscripten -D NUMKONG_MARCH=v128relaxed && cmake --build --preset wasm32_emscripten
npm run build-js && npm run build-browser
npm run test:wasm:emscripten
```

### Native Addon and WASM Runtimes

The top-level package is native-first.
It loads the compiled addon through `node-gyp-build`.

The repository also ships WASM wrappers.
Those are useful for portable or sandboxed environments.
They are not feature-complete replacements for the native SDKs.

Practical guidance:

- Use the native addon for lower host-call latency.
- Use the WASM path when portability matters more than absolute latency.
- Keep your expectations scoped to the vector and matrix-oriented API that this binding actually exports.

