diff --git a/js-wasm/README.md b/js-wasm/README.md
index dbae45065..18ca097e6 100644
--- a/js-wasm/README.md
+++ b/js-wasm/README.md
@@ -1,130 +1,132 @@
-# yara-x-wasm
+# @virustotal/yara-x
-Browser-focused WebAssembly packaging for [`yara-x`](../lib) with an
-object-oriented JavaScript API built around `Compiler`, `Rules`, and
-`Scanner`.
+JavaScript bindings for [YARA-X](https://github.com/VirusTotal/yara-x) using WebAssembly.
-## Package surface
-
-- `Compiler`, `Rules`, and `Scanner`
-
-## Build
-
-From [`js-wasm`](.) run:
-
-```bash
-cargo install --locked wasm-pack --version 0.14.0
-cargo install --locked wasm-bindgen-cli --version 0.2.113
-wasm-pack build --target web --release --mode no-install --no-pack
-```
-
-This produces the standard browser package in `pkg/`.
-
-For the full package layout, including the preserved no-modules bundles in
-`dist/`:
-
-```bash
-cargo run --release --features release-tools --bin build_web_release --
-```
-
-or:
+## Installation
```bash
-cargo build-web-release
+npm install @virustotal/yara-x
```
-This produces:
+## Quick Start
-- `pkg/yara-x-wasm.js`
-- `pkg/yara-x-wasm_bg.wasm`
-- `dist/yara-x-wasm-bundle.js`
-- `dist/yara-x-wasm-bundle.min.js`
+```js
+import init, { Compiler } from "@virustotal/yara-x";
-The no-modules bundle reuses the shared `pkg/yara-x-wasm_bg.wasm` binary
-instead of shipping a second copy under `dist/`.
+// Initialize the WebAssembly module
+await init();
-SIMD is enabled for `wasm32-unknown-unknown` via `js-wasm/.cargo/config.toml`.
+// Compile a rule
+const compiler = new Compiler();
+compiler.addSource('rule test { strings: $a = "abc" condition: $a }');
-## Tests
+const rules = compiler.build();
-Rust/browser API coverage:
+// Scan data
+const payload = new Uint8Array([0x61, 0x62, 0x63, 0x64]); // "abcd"
+const result = rules.scan(payload);
-```bash
-npm run test:wasm-node
+if (result.valid && result.matches.length > 0) {
+ console.log("Rule matched!");
+}
```
-Headless browser coverage for browser-specific behavior such as console output:
-
-```bash
-CHROME_BIN=/path/to/chrome \
-CHROMEDRIVER=/path/to/chromedriver \
-npm run test:wasm-browser
+## API Reference
+
+### `Compiler`
+
+The `Compiler` translates YARA-X rules into a executable format.
+
+- `addSource(source: string)`: Compiles a rule string. Throws an error if compilation fails.
+- `build(): Rules`: Finalizes compilation and returns a `Rules` object.
+- `defineGlobal(identifier: string, value: any)`: Defines an external variable used in conditions (boolean, number, string).
+- `newNamespace(namespace: string)`: Scopes subsequent rules to a specific namespace.
+- `errors: string[]`: Array of compilation error messages.
+- `warnings: string[]`: Array of compilation warning messages.
+
+### `Rules`
+
+The `Rules` object represents the compiled set of rules ready for scanning.
+
+- `scan(payload: Uint8Array): ScanResult`: Scans the payload using the default scanner profile.
+- `scanner(): Scanner`: Spawns a dedicated `Scanner` for advanced configuration.
+- `warnings: string[]`: Warnings inherited from the compiler.
+
+### `Scanner`
+
+The `Scanner` provides fine-grained control over scanning operations.
+
+- `scan(payload: Uint8Array): ScanResult`: Scans the payload.
+- `setGlobal(identifier: string, value: any)`: Overrides values defined by `compiler.defineGlobal()`.
+- `setMaxMatchesPerPattern(n: number)`: Limits reporting to first `n` matches per pattern.
+- `setTimeoutMs(timeout_ms: number)`: Sets a hard timeout for scanning.
+
+---
+
+## Scan Results Structure
+
+The `.scan(...)` methods return an object detailing matches and diagnostics:
+
+```json
+{
+ "valid": true,
+ "matches": [
+ {
+ "identifier": "rule_name",
+ "namespace": "default",
+ "isPrivate": false,
+ "isGlobal": false,
+ "tags": ["tag_a"],
+ "metadata": [
+ { "identifier": "key", "value": "value" }
+ ],
+ "patterns": [
+ {
+ "identifier": "$a",
+ "kind": "text",
+ "isPrivate": false,
+ "matches": [
+ { "offset": 2, "length": 3 }
+ ]
+ }
+ ]
+ }
+ ],
+ "warnings": []
+}
```
-JS end-to-end coverage against the generated `pkg/` + `dist/` outputs:
+---
-```bash
-npm run test:js
-```
+## Resource Management
-Package validation:
+Objects generated in WebAssembly live in the Wasm heap, which is separate from the JavaScript garbage-collected
+heap. If you do not manually free these objects, they will leak memory in the WebAssembly space.
-```bash
-npm run pack:dry-run
-```
-
-## Usage
-
-### ES module usage:
+Ensure you call `.free()` on objects when no longer needed:
```js
-import init, { Compiler } from "yara-x-wasm";
-
-await init();
-
const compiler = new Compiler();
-compiler.addSource('rule x { strings: $a = "abc" condition: $a }');
-
-const rules = compiler.build();
-const result = rules.scan(new Uint8Array([0x61, 0x62, 0x63]));
+try {
+ compiler.addSource('rule x { condition: true }');
+ const rules = compiler.build();
+ const payload = new Uint8Array([0x00]); // Self-contained payload
+ rules.scan(payload);
+ rules.free();
+} finally {
+ compiler.free();
+}
```
-### No-modules bundle usage:
-
-```html
-
-
-```
-
-Use `dist/yara-x-wasm-bundle.min.js` instead of `dist/yara-x-wasm-bundle.js` for
-production deployments. By default the bundle loads its wasm from
-`pkg/yara-x-wasm_bg.wasm`, so keep the standard package layout intact when
-serving it.
-
-### Object-style API with scanner configuration:
+If your environment supports the new JavaScript `using` keyword (Explicit Resource Management), you can let the
+runtime handle it automatically because the types implement `[Symbol.dispose]`:
```js
-import init, { Compiler, Scanner } from "yara-x-wasm";
-
-await init();
-
-const compiler = new Compiler();
-compiler.defineGlobal("threshold", 7);
-compiler.addSource('rule x { condition: threshold == 7 }');
-
-const rules = compiler.build();
-const scanner = new Scanner(rules);
-scanner.setGlobal("threshold", 9);
+{
+ using compiler = new Compiler();
+ compiler.addSource('rule x { condition: true }');
+} // compiler.free() is called automatically here!
```
+