diff --git a/docz/data/engines.js b/docz/data/engines.js
new file mode 100644
index 0000000..6640ceb
--- /dev/null
+++ b/docz/data/engines.js
@@ -0,0 +1,21 @@
+import { read, utils } from 'xlsx';
+import url from './engines.xls';
+import React, { useEffect, useState } from 'react';
+
+const EngineData = () => {
+  const [engines, setEngines] = useState("");
+  const [binding, setBinding] = useState("");
+
+  useEffect(() => { (async() => {
+    const wb = read(await (await fetch(url)).arrayBuffer(), { dense: true });
+    setEngines(utils.sheet_to_html(wb.Sheets["Engines"]));
+    setBinding(utils.sheet_to_html(wb.Sheets["Bindings"]));
+  })(); }, []);
+  return ( <>
+    
The following engines have been tested in their native languages:
+    
+    The following bindings have been tested:
+    
+  > );
+};
+export default EngineData;
\ No newline at end of file
diff --git a/docz/data/engines.xls b/docz/data/engines.xls
new file mode 100644
index 0000000..b0b0ade
--- /dev/null
+++ b/docz/data/engines.xls
@@ -0,0 +1,321 @@
+
+
+
+ 
+  10620
+  11020
+  2260
+  19600
+  1
+  False
+  False
+ 
+ 
+  
+  
+  
+  
+ 
+ 
+  
+   
+   
+   
+   
+   
+   
+   
+    | + | MacOS+ | Windows+ | Linux+ | 
+   
+    | Engine+ | Lang+ | x64+ | ARM+ | x64+ | ARM+ | x64+ | ARM+ | 
+   
+    | Duktape+ | C+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | V8+ | C+++ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | + | 
+   
+    | Rhino+ | Java+ | ✔+ | + | + | + | ✔+ | + | 
+   
+    | Jint+ | C#+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | Goja+ | Go+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | Nashorn+ | Java+ | ✔+ | + | + | + | ✔+ | + | 
+   
+    | QuickJS+ | C+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | Hermes+ | C+++ | ✔+ | ✔+ | ✔+ | + | ✔+ | ✔+ | 
+   
+    | ChakraCore+ | C+++ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | Boa+ | Rust+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | JE+ | Perl+ | ✔+ | + | + | + | ✔+ | + | 
+   
+    | JerryScript+ | C+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+  
+  
+   
+    
+    
+    
+   
+   
+   
+   2
+   2
+   2
+   
+    
+     3
+    
+    
+     2
+     12
+     5
+    
+   
+   False
+   False
+  
+ 
+ 
+  
+   
+   
+   
+   
+   
+   
+   
+    | + | MacOS+ | Windows+ | Linux+ | 
+   
+    | Engine+ | Binding+ | x64+ | ARM+ | x64+ | ARM+ | x64+ | ARM+ | 
+   
+    | Duktape+ | Perl+ | ✔+ | + | + | + | ✔+ | + | 
+   
+    | Duktape+ | PHP+ | ✔+ | + | + | + | + | + | 
+   
+    | V8+ | Rust+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+   
+    | V8+ | Python+ | ✔+ | + | + | + | + | + | 
+   
+    | JSC+ | Swift+ | ✔+ | ✔+ | + | + | + | + | 
+   
+    | ExecJS+ | Ruby+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | ✔+ | 
+  
+  
+   
+    
+    
+    
+   
+   
+   
+   
+   2
+   2
+   2
+   
+    
+     3
+    
+    
+     2
+     3
+     1
+    
+   
+   False
+   False
+  
+ 
+
diff --git a/docz/docs/03-demos/03-net/08-headless.md b/docz/docs/03-demos/03-net/08-headless.md
index 61f4dc5..8c49653 100644
--- a/docz/docs/03-demos/03-net/08-headless.md
+++ b/docz/docs/03-demos/03-net/08-headless.md
@@ -76,8 +76,8 @@ the automation context is more efficient and strongly recommended.
 
 ## Puppeteer
 
-Puppeteer enables headless Chromium automation for NodeJS.  Releases ship with
-an installer script that prepares a compatible browser version.
+[Puppeteer](https://pptr.dev/) enables headless Chromium automation for NodeJS.
+Releases ship with an installer script that installs a headless browser.
 
 
   
@@ -127,16 +127,16 @@ const puppeteer = require('puppeteer');
 
 **Demo**
 
-:::note
+:::note Tested Deployments
 
-This demo was last tested on 2023 September 14 against Puppeteer 21.2.1.
+This demo was last tested on 2024 January 27 against Puppeteer 21.9.0.
 
 :::
 
 1) Install SheetJS and Puppeteer:
 
 {`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@21.2.1`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@21.9.0`}
 
 
 2) Save the `SheetJSPuppeteer.js` code snippet to `SheetJSPuppeteer.js`.
@@ -202,9 +202,9 @@ await browser.close();`}
 
 **Demo**
 
-:::note
+:::note Tested Deployments
 
-This demo was last tested on 2023 September 14 against deno-puppeteer 16.2.0.
+This demo was last tested on 2024 January 27 against deno-puppeteer 16.2.0.
 
 :::
 
@@ -242,9 +242,9 @@ This file can be opened with Excel.
 
 ## Playwright
 
-Playwright presents a unified scripting framework for Chromium, WebKit, and
-other browsers.  It draws inspiration from Puppeteer.  In fact, the example
-code is almost identical!
+[Playwright](https://playwright.dev/) presents a unified scripting framework for
+Chromium, WebKit, and other browsers. It draws inspiration from Puppeteer. In
+fact, the example code is almost identical!
 
 Differences from the Puppeteer example are highlighted below:
 
@@ -290,16 +290,16 @@ const { webkit } = require('playwright'); // import desired browser
 
 **Demo**
 
-:::note
+:::note Tested Deployments
 
-This demo was last tested on 2023 September 14 against Playwright 1.38.0.
+This demo was last tested on 2024 January 27 against Playwright 1.41.1.
 
 :::
 
 1) Install SheetJS and Playwright:
 
 {`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.33.0`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.41.1`}
 
 
 2) Save the `SheetJSPlaywright.js` code snippet to `SheetJSPlaywright.js`.
@@ -315,7 +315,7 @@ This file can be opened with Excel.
 
 :::caution pass
 
-In the latest Windows 10 test, the commmand failed with a clear error message:
+The commmand may fail with a message such as:
 
 ```
 ╔═════════════════════════════════════════════════════════════════════════╗
@@ -328,13 +328,13 @@ In the latest Windows 10 test, the commmand failed with a clear error message:
 ╚═════════════════════════════════════════════════════════════════════════╝
 ```
 
-As recommended, the command
+Running the recommended command will download and install browser engines:
 
 ```bash
 npx playwright install
 ```
 
-will download and install the browsers.
+After installing engines, re-run the script.
 
 :::
 
@@ -398,13 +398,13 @@ strongly recommended to add verbose logging and to lint scripts before use.
 
 **Demo**
 
-:::note
+:::note Tested Deployments
 
 This demo was last tested on 2023 September 14 against PhantomJS 2.1.1
 
 :::
 
-1) Download and unzip the PhantomJS release from the official website[^1].
+1) [Download and extract PhantomJS](https://phantomjs.org/download.html)
 
 2) Save the `SheetJSPhantom.js` code snippet to `SheetJSPhantom.js`.
 
@@ -421,5 +421,3 @@ When the script finishes, the file `SheetJSPhantomJS.xlsb` will be created.
 This file can be opened with Excel.
 
 
-
-[^1]: Downloads available at 
\ No newline at end of file
diff --git a/docz/docs/03-demos/03-net/09-dom.md b/docz/docs/03-demos/03-net/09-dom.md
index ad20d1b..3b0698c 100644
--- a/docz/docs/03-demos/03-net/09-dom.md
+++ b/docz/docs/03-demos/03-net/09-dom.md
@@ -30,6 +30,27 @@ web browser. ["Browser Automation"](/docs/demos/net/headless) includes demos.
 
 ## Integration Details
 
+Synthetic DOM implementations typically provide a function that accept a HTML
+string and return an object that represents `document`. An API method such as
+`getElementsByTagName` or `querySelector` can pull TABLE elements.
+
+```mermaid
+flowchart LR
+	subgraph Synthetic DOM Operations
+		html(HTML\nstring)
+    doc{{`document`\nDOM Object}}
+	end
+	subgraph SheetJS Operations
+		table{{DOM\nTable}}
+	  wb(((SheetJS\nWorkbook)))
+  	file(workbook\nfile)
+	end
+  html --> |Library\n\n| doc
+  doc --> |DOM\nAPI| table
+  table --> |`table_to_book`\n\n| wb
+	wb --> |`writeFile`\n\n| file
+```
+
 SheetJS methods use features that may be missing from some DOM implementations.
 
 ### Table rows
@@ -37,8 +58,8 @@ SheetJS methods use features that may be missing from some DOM implementations.
 The `rows` property of TABLE elements is a list of TR row children. This list
 automatically updates when rows are added and deleted.
 
-SheetJS does not mutate `rows`. Assuming there are no nested tables, the `rows`
-property can be created using `getElementsByTagName`:
+SheetJS methods do not mutate `rows`. Assuming there are no nested tables, the
+`rows` property can be created using `getElementsByTagName`:
 
 ```js
 tbl.rows = Array.from(tbl.getElementsByTagName("tr"));
@@ -49,7 +70,7 @@ tbl.rows = Array.from(tbl.getElementsByTagName("tr"));
 The `cells` property of TR elements is a list of TD cell children. This list
 automatically updates when cells are added and deleted.
 
-SheetJS does not mutate `cells`. Assuming there are no nested tables, the
+SheetJS methods do not mutate `cells`. Assuming there are no nested tables, the
 `cells` property can be created using `getElementsByTagName`:
 
 ```js
@@ -89,14 +110,14 @@ XLSX.writeFile(workbook, "SheetJSDOM.xlsx");
 
 :::note Tested Deployments
 
-This demo was last tested on 2023 September 10 against JSDOM `22.1.0`
+This demo was last tested on 2024 January 27 against JSDOM `24.0.0`
 
 :::
 
 1) Install SheetJS and JSDOM libraries:
 
 {`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz jsdom@22.0.0`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz jsdom@24.0.0`}
 
 
 2) Save the previous codeblock to `SheetJSDOM.js`.
@@ -119,7 +140,7 @@ The script will create a file `SheetJSDOM.xlsx` that can be opened.
 
 ### HappyDOM
 
-HappyDOM provides a DOM framework for NodeJS. For the tested version (`11.0.2`),
+HappyDOM provides a DOM framework for NodeJS. For the tested version (`13.3.1`),
 the following patches were needed:
 
 - TABLE `rows` property (explained above)
@@ -129,14 +150,14 @@ the following patches were needed:
 
 :::note Tested Deployments
 
-This demo was last tested on 2023 September 10 against HappyDOM `11.0.2`
+This demo was last tested on 2024 January 27 against HappyDOM `13.3.1`
 
 :::
 
 1) Install SheetJS and HappyDOM libraries:
 
 {`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz happy-dom@11.0.2`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz happy-dom@13.3.1`}
 
 
 2) Download [the sample script `SheetJSHappyDOM.js`](pathname:///dom/SheetJSHappyDOM.js):
@@ -145,7 +166,13 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz happy-d
 curl -LO https://docs.sheetjs.com/dom/SheetJSHappyDOM.js
 ```
 
-3) Run the script:
+3) Download [the sample `SheetJSTable.html`](pathname:///dom/SheetJSTable.html):
+
+```bash
+curl -LO https://docs.sheetjs.com/dom/SheetJSTable.html
+```
+
+4) Run the script:
 
 ```bash
 node SheetJSHappyDOM.js
@@ -256,7 +283,7 @@ The script will create a file `SheetJSCheerio.xlsx` that can be opened.
 ### DenoDOM
 
 [DenoDOM](https://deno.land/x/deno_dom) provides a DOM framework for Deno. For
-the tested version (`0.1.38`), the following patches were needed:
+the tested version (`0.1.43`), the following patches were needed:
 
 - TABLE `rows` property (explained above)
 - TR `cells` property (explained above)
@@ -267,7 +294,7 @@ This example fetches [a sample table](pathname:///dom/SheetJSTable.html):
 // @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
 import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
 \n\
-import { DOMParser } from 'https://deno.land/x/deno_dom@v0.1.38/deno-dom-wasm.ts';
+import { DOMParser } from 'https://deno.land/x/deno_dom@v0.1.43/deno-dom-wasm.ts';
 \n\
 const doc = new DOMParser().parseFromString(
   await (await fetch('https://docs.sheetjs.com/dom/SheetJSTable.html')).text(),
@@ -290,7 +317,7 @@ XLSX.writeFile(workbook, "SheetJSDenoDOM.xlsx");`}
 
 :::note Tested Deployments
 
-This demo was last tested on 2023 September 10 against DenoDOM `0.1.38`
+This demo was last tested on 2024 January 27 against DenoDOM `0.1.43`
 
 :::
 
diff --git a/docz/docs/03-demos/19-desktop/01-electron.md b/docz/docs/03-demos/19-desktop/01-electron.md
index 9ce26a2..93f8699 100644
--- a/docz/docs/03-demos/19-desktop/01-electron.md
+++ b/docz/docs/03-demos/19-desktop/01-electron.md
@@ -123,7 +123,7 @@ async function importFile() {
 
 :::note pass
 
-In older versions of Electron, `showOpenDialog` returned the path directly:
+`showOpenDialog` originally returned an array of paths:
 
 ```js
 var dialog = require('electron').remote.dialog;
@@ -134,6 +134,8 @@ function importFile(workbook) {
 }
 ```
 
+This method was renamed to `showOpenDialogSync` in Electron 6.
+
 :::
 
 ### Writing Files
@@ -163,7 +165,7 @@ async function exportFile(workbook) {
 
 :::note pass
 
-In older versions of Electron, `showSaveDialog` returned the path directly:
+`showSaveDialog` originally returned the selected path:
 
 ```js
 var dialog = require('electron').remote.dialog;
@@ -174,6 +176,8 @@ function exportFile(workbook) {
 }
 ```
 
+This method was renamed to `showSaveDialogSync` in Electron 6.
+
 :::
 
 ## Complete Example
@@ -188,7 +192,7 @@ This demo was tested in the following environments:
 | macOS 14.1.2   | `darwin-arm` | `27.1.3` | 2023-12-01 |
 | Windows 10     | `win10-x64`  | `27.1.3` | 2023-12-09 |
 | Windows 11     | `win11-arm`  | `27.1.3` | 2023-12-01 |
-| Linux (HoloOS) | `linux-x64`  | `27.1.3` | 2023-12-09 |
+| Linux (HoloOS) | `linux-x64`  | `28.2.0` | 2024-01-26 |
 | Linux (Debian) | `linux-arm`  | `27.1.3` | 2023-12-01 |
 
 :::
@@ -315,25 +319,30 @@ and select `pres.numbers`.
 ## Electron Breaking Changes
 
 The first version of this demo used Electron 1.7.5.  The current demo includes
-the required changes for Electron 27.1.3.
+the required changes for Electron 28.2.0.
 
 There are no Electron-specific workarounds in the library, but Electron broke
 backwards compatibility multiple times.  A summary of changes is noted below.
 
 :::caution pass
 
-Electron 6.x changed the `dialog` API. Methods like `showSaveDialog` originally
-returned an array of strings, but now returns a `Promise`.  This change was not
-documented.
+Electron 6 changed the return types of `dialog` API methods. The old `dialog`
+methods have been renamed:
 
-Electron 9.0.0 and later require the preference `nodeIntegration: true` in order
-to `require('xlsx')` in the renderer process.
+| Electron 1 - 5   | Electron 6           |
+|:-----------------|:---------------------|
+| `showOpenDialog` | `showOpenDialogSync` |
+| `showSaveDialog` | `showSaveDialogSync` |
+**This change was not properly documented!**
 
-Electron 12.0.0 and later also require `worldSafeExecuteJavascript: true` and
+Electron 9 and later require the preference `nodeIntegration: true` in order to
+`require('xlsx')` in the renderer process.
+
+Electron 12 and later also require `worldSafeExecuteJavascript: true` and
 `contextIsolation: true`.
 
-Electron 14+ must use `@electron/remote` instead of `remote`.  An `initialize`
-call is required to enable Developer Tools in the window.
+Electron 14 and later must use `@electron/remote` instead of `remote`. An
+`initialize` call is required to enable Developer Tools in the window.
 
 :::
 
diff --git a/docz/docs/03-demos/19-desktop/02-nwjs.md b/docz/docs/03-demos/19-desktop/02-nwjs.md
index eb59c52..f8dd493 100644
--- a/docz/docs/03-demos/19-desktop/02-nwjs.md
+++ b/docz/docs/03-demos/19-desktop/02-nwjs.md
@@ -117,7 +117,7 @@ This demo was tested in the following environments:
 | macOS 14.1.2   | `darwin-arm` | `0.82.0` | 2023-12-01 |
 | Windows 10     | `win10-x64`  | `0.82.0` | 2023-12-09 |
 | Windows 11     | `win11-arm`  | `0.82.0` | 2023-12-01 |
-| Linux (HoloOS) | `linux-x64`  | `0.82.0` | 2023-12-07 |
+| Linux (HoloOS) | `linux-x64`  | `0.83.0` | 2024-01-26 |
 
 There is no official Linux ARM64 release. The community release[^1] was tested
 and verified on 2023-09-27.
@@ -140,7 +140,7 @@ cd sheetjs-nwjs
   "version": "0.0.0",
   "main": "index.html",
   "dependencies": {
-    "nw": "0.82.0",
+    "nw": "0.83.0",
     "xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
   }
 }`}
@@ -179,7 +179,7 @@ the file input element to select a spreadsheet and clicking the export button.
 5) To build a standalone app, run the builder:
 
 ```bash
-npx -p nw-builder nwbuild --mode=build --version=0.82.0 --glob=false --outDir=../out ./
+npx -p nw-builder nwbuild --mode=build --version=0.83.0 --glob=false --outDir=../out ./
 ```
 
 This will generate the standalone app in the `..\out\` folder.
diff --git a/docz/docs/03-demos/19-desktop/05-neutralino.md b/docz/docs/03-demos/19-desktop/05-neutralino.md
index 105920d..5a8e8e0 100644
--- a/docz/docs/03-demos/19-desktop/05-neutralino.md
+++ b/docz/docs/03-demos/19-desktop/05-neutralino.md
@@ -196,7 +196,7 @@ This demo was tested in the following environments:
 | macOS 14.0     | `darwin-arm` | `v4.14.1` | `v3.12.0` | 2023-10-18 |
 | Windows 10     | `win10-x64`  | `v4.14.1` | `v3.12.0` | 2023-12-09 |
 | Windows 11     | `win11-arm`  | `v4.14.1` | `v3.12.0` | 2023-12-01 |
-| Linux (HoloOS) | `linux-x64`  | `v4.14.1` | `v3.12.0` | 2023-12-09 |
+| Linux (HoloOS) | `linux-x64`  | `v4.14.1` | `v3.12.0` | 2024-01-26 |
 | Linux (Debian) | `linux-arm`  | `v4.14.1` | `v3.12.0` | 2023-12-01 |
 
 :::
@@ -238,7 +238,7 @@ curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-${current}
 
 3) Add the highlighted line to `neutralino.config.json` in `nativeAllowList`:
 
-```json title="neutralino.config.json"
+```json title="neutralino.config.json (add highlighted line)"
   "nativeAllowList": [
     "app.*",
     "os.*",
diff --git a/docz/docs/03-demos/19-desktop/09-cli.md b/docz/docs/03-demos/19-desktop/09-cli.md
index 8560591..e043d35 100644
--- a/docz/docs/03-demos/19-desktop/09-cli.md
+++ b/docz/docs/03-demos/19-desktop/09-cli.md
@@ -49,37 +49,37 @@ This demo was tested in the following deployments:
 
   
 
-| Architecture | Version      | Node Target | Date       |
-|:-------------|:-------------|:------------|:-----------|
-| `darwin-x64` | `4.0.0-rc.2` | `14.15.3`   | 2023-10-10 |
-| `darwin-arm` | `4.0.0-rc.2` | `18.18.0`   | 2023-12-01 |
-| `win10-x64`  | `4.0.0-rc.2` | `14.15.3`   | 2023-10-09 |
-| `win11-arm`  | `4.0.0-rc.2` | `20.10.0`   | 2023-12-01 |
-| `linux-x64`  | `4.0.0-rc.2` | `14.15.3`   | 2023-12-07 |
-| `linux-arm`  | `4.0.0-rc.2` | `20.10.0`   | 2023-12-01 |
+| Architecture | Version      | NodeJS    | Source    | Date       |
+|:-------------|:-------------|:----------|:----------|:-----------|
+| `darwin-x64` | `4.0.0-rc.2` | `14.15.3` | Pre-built | 2023-10-10 |
+| `darwin-arm` | `4.0.0-rc.2` | `18.18.0` | Compiled  | 2023-12-01 |
+| `win10-x64`  | `4.0.0-rc.2` | `14.15.3` | Pre-built | 2023-10-09 |
+| `win11-arm`  | `4.0.0-rc.2` | `20.10.0` | Compiled  | 2023-12-01 |
+| `linux-x64`  | `4.0.0-rc.4` | `14.15.3` | Pre-built | 2024-01-26 |
+| `linux-arm`  | `4.0.0-rc.2` | `20.10.0` | Compiled  | 2023-12-01 |
 
   
   
 
-| Architecture | Version | Node Target | Date       |
-|:-------------|:--------|:------------|:-----------|
-| `darwin-x64` | `5.8.1` | `18.5.0`    | 2023-10-11 |
-| `darwin-arm` | `5.8.1` | `18.5.0`    | 2023-12-01 |
-| `win10-x64`  | `5.8.1` | `18.5.0`    | 2023-10-09 |
-| `win11-arm`  | `5.8.1` | `18.5.0`    | 2023-12-01 |
-| `linux-x64`  | `5.8.1` | `18.5.0`    | 2023-12-07 |
-| `linux-arm`  | `5.8.1` | `18.5.0`    | 2023-12-01 |
+| Architecture | Version | NodeJS   | Date       |
+|:-------------|:--------|:---------|:-----------|
+| `darwin-x64` | `5.8.1` | `18.5.0` | 2023-10-11 |
+| `darwin-arm` | `5.8.1` | `18.5.0` | 2023-12-01 |
+| `win10-x64`  | `5.8.1` | `18.5.0` | 2023-10-09 |
+| `win11-arm`  | `5.8.1` | `18.5.0` | 2023-12-01 |
+| `linux-x64`  | `5.8.1` | `18.5.0` | 2024-01-26 |
+| `linux-arm`  | `5.8.1` | `18.5.0` | 2023-12-01 |
 
   
   
 
-| Architecture | Version | Node Target | Date       |
-|:-------------|:--------|:------------|:-----------|
-| `darwin-x64` | `2.1.2` | `20.8.0`    | 2023-10-12 |
-| `darwin-arm` | `2.3.0` | `21.3.0`    | 2023-12-01 |
-| `win10-x64`  | `2.1.2` | `16.20.2`   | 2023-10-09 |
-| `linux-x64`  | `2.3.0` | `21.4.0`    | 2023-12-07 |
-| `linux-arm`  | `2.3.0` | `21.3.0`    | 2023-12-01 |
+| Architecture | Version | NodeJS    | Date       |
+|:-------------|:--------|:----------|:-----------|
+| `darwin-x64` | `2.1.2` | `20.8.0`  | 2023-10-12 |
+| `darwin-arm` | `2.3.0` | `21.3.0`  | 2023-12-01 |
+| `win10-x64`  | `2.1.2` | `16.20.2` | 2023-10-09 |
+| `linux-x64`  | `2.3.0` | `21.6.1`  | 2024-01-26 |
+| `linux-arm`  | `2.3.0` | `21.3.0`  | 2023-12-01 |
 
   
 
@@ -309,7 +309,7 @@ This demo was last tested in the following deployments:
 | `darwin-arm` | `11.8.172.13` | `0.79.2` | 2023-10-18 |
 | `win10-x64`  | `11.8.172.13` | `0.79.2` | 2023-10-09 |
 | `win11-x64`  | `11.8.172.13` | `0.79.2` | 2023-10-14 |
-| `linux-x64`  | `11.8.172.13` | `0.79.2` | 2023-10-11 |
+| `linux-x64`  | `12.0.267.8`  | `0.83.1` | 2024-01-26 |
 | `linux-arm`  | `12.0.267.8`  | `0.82.0` | 2023-12-01 |
 
 :::
diff --git a/docz/docs/03-demos/30-cloud/02-netsuite.md b/docz/docs/03-demos/30-cloud/02-netsuite.md
index e520cd2..8bd158f 100644
--- a/docz/docs/03-demos/30-cloud/02-netsuite.md
+++ b/docz/docs/03-demos/30-cloud/02-netsuite.md
@@ -26,11 +26,18 @@ This demo was verified by NetSuite consultants in the following deployments:
 |:----------------|:---------------|:-----------|
 | ScheduledScript | 2.1            | 2023-12-13 |
 | Restlet         | 2.1            | 2023-10-05 |
-| Suitelet        | 2.1            | 2024-01-17 |
+| Suitelet        | 2.1            | 2024-01-26 |
 | MapReduceScript | 2.1            | 2023-12-07 |
 
 :::
 
+:::info pass
+
+[See issue #3058](https://git.sheetjs.com/sheetjs/sheetjs/issues/3058) in the
+issue tracker for more examples submitted by NetSuite consultants.
+
+:::
+
 ## Installation
 
 In SuiteScript parlance, third-party scripts are "Custom Modules"[^2].
@@ -126,6 +133,19 @@ define(
 
 ### Reading Files
 
+```mermaid
+flowchart LR
+  subgraph NetSuite Operations
+    cab[(File\nCabinet)]
+    file(File)
+    base64{{Base64\nString}}
+  end
+  wb(((SheetJS\nWorkbook)))
+  cab --> |`load`\nN/file| file
+  file --> |`getContents`\nFile method| base64
+  base64 --> |`read`\nSheetJS| wb
+```
+
 There are three steps to reading files:
 
 1) Pull files from the file cabinet using `file.load`[^7]. The method returns a
@@ -156,6 +176,19 @@ workbook object.
 
 ### Writing Files
 
+```mermaid
+flowchart LR
+  wb(((SheetJS\nWorkbook)))
+  subgraph NetSuite Operations
+    base64{{Base64\nString}}
+    file(File)
+    cab[(File\nCabinet)]
+  end
+  wb --> |`write`\nSheetJS| base64
+  base64 --> |`create`\nN/file| file
+  file --> |`save`\nFile method| cab
+```
+
 There are three steps to writing files:
 
 1) Write the data with the SheetJS `write` method[^11]. Using the `base64` output
@@ -171,7 +204,7 @@ There are three steps to writing files:
 var out = XLSX.write(workbook, { bookType: "xlsx", type: "base64" });
 /* create file */
 var newfile = file.create({
-  name: 'test.xlsx', // replace with desired name
+  name: 'SheetJSCabinetExport.xlsx', // replace with desired name
   fileType: file.Type.EXCEL,
   contents: out
 });
@@ -179,6 +212,137 @@ var newfile = file.create({
 newfile.save();
 ```
 
+## Sheets in Suitelet Requests
+
+Suitelets are driven by an exported `onRequest` method[^15].
+
+The `request` property of the argument is a `ServerRequest` object[^16]. The
+`files` property of the request[^17] is an object whose values are `file` objects.
+
+The `response` property of the argument is a `ServerResponse` object[^18]. The
+`writeFile` method[^19] of the response can respond with a `file` object.
+For the examples in this section, the argument will be named `context`:
+
+```js
+/**
+ * @NApiVersion 2.1
+ * @NAmdConfig ./JsLibraryConfig.json
+ * @NScriptType Suitelet
+ */
+define(['N/file', 'xlsx'], function (file, XLSX) {
+  function onRequest(context) {
+    /* ServerRequest object */
+    var request = context.request;
+
+    /* ServerResponse object */
+    var response = context.response;
+
+    // ... do work here ...
+  }
+
+  return { onRequest: onRequest };
+});
+```
+
+### Importing Sheet Data
+
+```mermaid
+flowchart LR
+  subgraph NetSuite Operations
+    req((Suitelet\nRequest))
+    file(File)
+    base64{{Base64\nString}}
+  end
+  wb(((SheetJS\nWorkbook)))
+  req --> |`files`\nrequest data| file
+  file --> |`getContents`\nFile method| base64
+  base64 --> |`read`\nSheetJS| wb
+```
+
+There are three steps to importing data from Suitelet requests:
+
+1) Pull files from the `request.files` object.[^20]. Each value in the object is
+   a `file.File` object which represents the file metadata.
+
+2) Read raw data from the file using `File#getContents`[^21]. The method returns
+   the data as a Base64-encoded string.
+
+3) Parse the data with the SheetJS `read` method[^22]. This method returns a
+   SheetJS workbook object.
+
+```js
+/* form element ID or field name */
+var id_of_file = "uploaded_file"
+/* get file from request */
+var f = context.request.files[id_of_file];
+/* read file */
+var b64 = f.getContents();
+/* parse */
+var workbook = XLSX.read(b64, { type: "base64" });
+```
+
+At this point, standard SheetJS utility functions[^23] can extract data from the
+workbook object.
+
+:::note pass
+
+When programmatically creating a form with `N/ui/serverWidget`, the keys of the
+`files` object are determined by the `id` properties of the field.
+
+```js
+var form = serverWidget.createForm({ title: "Upload Spreadsheet" });
+var field = form.addField({
+// highlight-next-line
+  id: "uploaded_file",
+  label: "Choose Spreadsheet",
+  type: serverWidget.FieldType.FILE
+});
+```
+
+Since the `id` of the file field is `uploaded_file`, the request handler can
+access the file at at `context.request.files["uploaded_file"]`
+
+:::
+
+### Exporting Files
+
+```mermaid
+flowchart LR
+  wb(((SheetJS\nWorkbook)))
+  subgraph NetSuite Operations
+    base64{{Base64\nString}}
+    file(File)
+    res[(Suitelet\nResponse)]
+  end
+  wb --> |`write`\nSheetJS| base64
+  base64 --> |`create`\nN/file| file
+  file --> |`writeFile`\nResponse method| res
+```
+
+There are three steps to generating downloadable files:
+
+1) Write the data with the SheetJS `write` method[^24]. Using the `base64` output
+   type[^25], the method will return a Base64 string.
+
+2) Create a new file using `file.create`[^26]. The recommended file type is
+   `file.Type.EXCEL`. The method returns a `file.File` object.
+
+3) Initiate download with `response.writeFile`[^27].
+
+```js
+/* write XLSX workbook as Base64 string */
+var out = XLSX.write(workbook, { bookType: "xlsx", type: "base64" });
+/* create file */
+var newfile = file.create({
+  name: 'SheetJSSuiteletExport.xlsx', // replace with desired name
+  fileType: file.Type.EXCEL,
+  contents: out
+});
+/* initiate download */
+context.response.writeFile(newfile);
+```
+
+
 [^1]: See ["SuiteScript 2.x API Introduction"](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_4387172221.html) in the NetSuite documentation.
 [^2]: See ["SuiteScript 2.x Custom Modules"](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_4704097697.html) in the NetSuite documentation.
 [^3]: See ["Java + Rhino" demo](/docs/demos/engines/rhino)
@@ -191,5 +355,18 @@ newfile.save();
 [^10]: See ["Utility Functions"](/docs/api/utilities/)
 [^11]: See [`write` in "Writing Files"](/docs/api/write-options)
 [^12]: See ["Supported Output Formats"](/docs/api/write-options#supported-output-formats)
-[^13]: See [`file.create`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4223861820.html) in the NetSuite documentation.
-[^14]: See [`File.save()`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4229271179.html) in the NetSuite documentation.
\ No newline at end of file
+[^13]: See [`file.create(options)`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4223861820.html) in the NetSuite documentation.
+[^14]: See [`File.save()`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4229271179.html) in the NetSuite documentation.
+[^15]: See [`onRequest(params)`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4407987288.html) in the NetSuite documentation.
+[^16]: See [`http.ServerRequest`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4314608702.html) in the NetSuite documentation.
+[^17]: See [`ServerRequest.files`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4314805947.html) in the NetSuite documentation.
+[^18]: See [`http.ServerResponse`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4314609319.html) in the NetSuite documentation.
+[^19]: See [`ServerResponse.writeFile(options)`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4426015540.html) in the NetSuite documentation.
+[^20]: See [`ServerRequest.files`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4314805947.html) in the NetSuite documentation.
+[^21]: See [`File.getContents()`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4229269811.html) in the NetSuite documentation.
+[^22]: See [`read` in "Reading Files"](/docs/api/parse-options)
+[^23]: See ["Utility Functions"](/docs/api/utilities/)
+[^24]: See [`write` in "Writing Files"](/docs/api/write-options)
+[^25]: See ["Supported Output Formats"](/docs/api/write-options#supported-output-formats)
+[^26]: See [`file.create(options)`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4223861820.html) in the NetSuite documentation.
+[^27]: See [`ServerResponse.writeFile(options)`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4426015540.html) in the NetSuite documentation.
diff --git a/docz/docs/03-demos/42-engines/01-duktape.md b/docz/docs/03-demos/42-engines/01-duktape.md
index 9f7f512..b578e80 100644
--- a/docz/docs/03-demos/42-engines/01-duktape.md
+++ b/docz/docs/03-demos/42-engines/01-duktape.md
@@ -134,7 +134,7 @@ This demo was tested in the following deployments:
 | `darwin-arm` | `2.7.0` | 2023-10-18 |
 | `win10-x64`  | `2.7.0` | 2023-10-27 |
 | `win11-arm`  | `2.7.0` | 2023-12-01 |
-| `linux-x64`  | `2.7.0` | 2023-12-07 |
+| `linux-x64`  | `2.7.0` | 2024-01-26 |
 | `linux-arm`  | `2.7.0` | 2023-12-01 |
 
 :::
@@ -347,9 +347,75 @@ sequenceDiagram
 Bindings exist for many languages. As these bindings require "native" code, they
 may not work on every platform.
 
+### PHP
+
+There is no official PHP binding to the Duktape library. Instead, this demo uses
+the raw `FFI` interface[^1] to the Duktape shared library.
+
+#### PHP Demo
+
+:::note Tested Deployments
+
+This demo was tested in the following deployments:
+
+| Architecture | Version | PHP Version | Date       |
+|:-------------|:--------|:------------|:-----------|
+| `darwin-x64` | `2.7.0` | `8.3.2`     | 2024-01-26 |
+
+:::
+
+0) Ensure `php` is installed and available on the system path.
+
+1) Build the Duktape shared library:
+
+```bash
+curl -LO https://duktape.org/duktape-2.7.0.tar.xz
+tar -xJf duktape-2.7.0.tar.xz
+cd duktape-2.7.0
+make -f Makefile.sharedlibrary
+cd ..
+```
+
+2) Copy the shared library to the current folder. When the demo was last tested,
+the file name was `libduktape.207.20700.so`:
+
+```bash
+cp duktape-*/libduktape.*.so .
+```
+
+3) Download the SheetJS Standalone script, shim script and test file. Move all
+three files to the project directory:
+
+
+
+{`\
+curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
+curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
+curl -LO https://sheetjs.com/pres.numbers`}
+
+
+4) Download [`SheetJSDuk.php`](pathname:///duk/SheetJSDuk.php):
+
+```bash
+curl -LO https://docs.sheetjs.com/duk/SheetJSDuk.php
+```
+
+5) Run the script:
+
+```bash
+php SheetJSDuk.php pres.numbers
+```
+
+If the program succeeded, the CSV contents will be printed to console and the
+file `sheetjsw.xlsb` will be created.  That file can be opened with Excel.
+
 ### Perl
 
-The Perl binding for Duktape is available as `JavaScript::Duktape` on CPAN.
+The Perl binding for Duktape is available as `JavaScript::Duktape::XS` on CPAN.
 
 The Perl binding does not have raw `Buffer` ops, so Base64 strings are used.
 
@@ -361,17 +427,17 @@ This demo was tested in the following deployments:
 
 | Architecture | Version | Date       |
 |:-------------|:--------|:-----------|
-| `darwin-x64` | `2.5.0` | 2023-10-26 |
-| `linux-arm`  | `2.5.0` | 2023-12-01 |
+| `darwin-x64` | `2.2.0` | 2024-01-26 |
+| `linux-x64`  | `2.2.0` | 2024-01-26 |
 
 :::
 
 0) Ensure `perl` and `cpan` are installed and available on the system path.
 
-1) Install the `JavaScript::Duktape` library:
+1) Install the `JavaScript::Duktape::XS` library:
 
 ```bash
-cpan install JavaScript::Duktape
+cpan install JavaScript::Duktape::XS
 ```
 
 :::note pass
@@ -379,7 +445,7 @@ cpan install JavaScript::Duktape
 On some systems, the command must be run as the root user:
 
 ```bash
-sudo cpan install JavaScript::Duktape
+sudo cpan install JavaScript::Duktape::XS
 ```
 
 :::
@@ -388,12 +454,12 @@ sudo cpan install JavaScript::Duktape
 
 ```perl title="SheetJSDuk.pl"
 # usage: perl SheetJSDuk.pl path/to/file
-use JavaScript::Duktape;
+use JavaScript::Duktape::XS;
 use File::Slurp;
 use MIME::Base64 qw( encode_base64 decode_base64 );
 
 # Initialize
-my $js = JavaScript::Duktape->new( max_memory => 256 * 1024 * 1024 );
+my $js = JavaScript::Duktape::XS->new({ max_memory_bytes => 256 * 1024 * 1024 });
 $js->eval("var global = (function(){ return this; }).call(null);");
 
 # Load the ExtendScript build
@@ -452,4 +518,6 @@ The fix is to install `File::Slurp` with `cpan`:
 sudo cpan install File::Slurp
 ```
 
-:::
\ No newline at end of file
+:::
+
+[^1]: See [Foreign Function Interface](https://www.php.net/manual/en/book.ffi.php) in the PHP documentation.
\ No newline at end of file
diff --git a/docz/docs/03-demos/42-engines/02-v8.md b/docz/docs/03-demos/42-engines/02-v8.md
index 446d075..816d8ad 100644
--- a/docz/docs/03-demos/42-engines/02-v8.md
+++ b/docz/docs/03-demos/42-engines/02-v8.md
@@ -30,7 +30,7 @@ covers V8 engine bindings for other programming languages.
 The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
 can be parsed and evaluated in a V8 context.
 
-_Initialize V8_
+### Initialize V8
 
 The official V8 `hello-world` example covers initialization and cleanup. For the
 purposes of this demo, the key variables are noted below:
@@ -50,7 +50,7 @@ v8::Local eval_code(v8::Isolate *isolate, v8::Local cont
 }
 ```
 
-_Load SheetJS Scripts_
+### Load SheetJS Scripts
 
 The main library can be loaded by reading the scripts from the file system and
 evaluating in the V8 context:
@@ -127,7 +127,7 @@ This demo was tested in the following deployments:
 | `12.1.131`    | `darwin-x64` | macOS 14.1    | `clang 15.0.0`   | 2023-11-15 |
 | `12.1.283`    | `darwin-arm` | macOS 14.1.2  | `clang 15.0.0`   | 2023-12-01 |
 | `12.0.265`    | `win10-x64`  | Windows 10    | `CL 19.37.32822` | 2023-10-28 |
-| `12.1.222`    | `linux-x64`  | HoloOS 3.5.7  | `gcc 13.1.1`     | 2023-11-27 |
+| `12.3.50`     | `linux-x64`  | HoloOS 3.5.7  | `gcc 13.1.1`     | 2024-01-26 |
 | `11.8.82`     | `linux-arm`  | Debian 12     | `gcc 12.2.0`     | 2023-12-01 |
 
 :::
@@ -406,11 +406,11 @@ The recommended fix is to delete the referenced folder and re-run `gclient sync`
 
 
 
-5) Checkout the desired version. The following command pulls `12.1.283`:
+5) Checkout the desired version. The following command pulls `12.3.50`:
 
 
 ```bash
-git checkout tags/12.1.283 -b sample
+git checkout tags/12.3.50 -b sample
 ```
 
 :::caution pass
@@ -418,14 +418,14 @@ git checkout tags/12.1.283 -b sample
 The official documentation recommends:
 
 ```bash
-git checkout refs/tags/12.1.283 -b sample -t
+git checkout refs/tags/12.3.50 -b sample -t
 ```
 
 This command failed in local testing:
 
 ```
-E:\v8\v8>git checkout refs/tags/12.1.283 -b sample -t
-fatal: cannot set up tracking information; starting point 'refs/tags/12.1.283' is not a branch
+E:\v8\v8>git checkout refs/tags/12.3.50 -b sample -t
+fatal: cannot set up tracking information; starting point 'refs/tags/12.3.50' is not a branch
 ```
 
 :::
@@ -473,7 +473,8 @@ warnings. The error messages included the tag `-Werror`:
 1 error generated.
 ```
 
-This was resolved by manually editing `out.gn/x64.release.sample/args.gn`:
+This was resolved by manually editing `out.gn/x64.release.sample/args.gn`. The
+option `treat_warnings_as_errors` should be set to `false`:
 
 ```ninja title="out.gn/x64.release.sample/args.gn (add to file)"
 treat_warnings_as_errors = false
@@ -815,7 +816,7 @@ This demo was last tested in the following deployments:
 | `darwin-x64` | `0.81.0` | 2023-11-14 |
 | `darwin-arm` | `0.82.0` | 2023-12-01 |
 | `win10-x64`  | `0.81.0` | 2023-11-14 |
-| `linux-x64`  | `0.81.0` | 2023-11-27 |
+| `linux-x64`  | `0.83.1` | 2024-01-26 |
 | `linux-arm`  | `0.82.0` | 2023-12-01 |
 
 :::
diff --git a/docz/docs/03-demos/42-engines/06-goja.md b/docz/docs/03-demos/42-engines/06-goja.md
index e9b0f2c..b726628 100644
--- a/docz/docs/03-demos/42-engines/06-goja.md
+++ b/docz/docs/03-demos/42-engines/06-goja.md
@@ -98,7 +98,7 @@ This demo was tested in the following deployments:
 | `darwin-arm` | `873a149`  | `1.21.3`   | 2023-10-18 |
 | `win10-x64`  | `b396bb4`  | `1.21.3`   | 2023-10-28 |
 | `win11-arm`  | `b396bb4`  | `1.21.1`   | 2023-12-01 |
-| `linux-x64`  | `fc55792`  | `1.21.3`   | 2023-10-11 |
+| `linux-x64`  | `b396bb4`  | `1.21.6`   | 2024-01-26 |
 | `linux-arm`  | `b396bb4`  | `1.21.4`   | 2023-12-01 |
 
 At the time of writing, Goja did not have proper version numbers. Versions are
diff --git a/docz/docs/03-demos/42-engines/09-hermes.md b/docz/docs/03-demos/42-engines/09-hermes.md
index 5976353..a369d3b 100644
--- a/docz/docs/03-demos/42-engines/09-hermes.md
+++ b/docz/docs/03-demos/42-engines/09-hermes.md
@@ -7,6 +7,8 @@ pagination_next: solutions/input
 ---
 
 import current from '/version.js';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
 import CodeBlock from '@theme/CodeBlock';
 
 [Hermes](https://hermesengine.dev/) is an embeddable JS engine written in C++.
@@ -26,7 +28,7 @@ command-line tool for reading data from files.
 :::info pass
 
 Many Hermes functions are not documented. The explanation was verified against
-commit `49e1930`.
+commit `90e2b47`.
 
 :::
 
@@ -106,7 +108,7 @@ be parsed and evaluated in a Hermes context.
 The main library can be loaded by reading the script from the file system and
 evaluating in the Hermes context.
 
-:::tip pass
+:::note pass
 
 There are nonstandard tricks to embed the entire script in the binary. There are
 language proposals such as `#embed` (mirroring the same feature in C23).
@@ -364,7 +366,7 @@ This demo was tested in the following deployments:
 |:-------------|:-----------|:-----------|
 | `darwin-x64` | `84732b3`  | 2023-11-14 |
 | `darwin-arm` | `2b4f949`  | 2023-10-18 |
-| `linux-x64`  | `2b4f949`  | 2023-10-11 |
+| `linux-x64`  | `90e2b47`  | 2024-01-26 |
 | `linux-arm`  | `84732b3`  | 2023-12-01 |
 
 The main Hermes source tree does not have Windows support. The `hermes-windows`
@@ -480,7 +482,28 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
 curl -LO https://sheetjs.com/pres.numbers`}
 
 
-7) Run the application:
+7) Copy the `libhermes` and `libjsi` libraries into the current folder:
+
+
+  
+
+```bash
+cp ./build_release/API/hermes/libhermes.so .
+cp ./build_release/jsi/libjsi.so .
+```
+
+  
+  
+
+```bash
+cp ./build_release/API/hermes/libhermes.dylib .
+cp ./build_release/jsi/libjsi.dylib .
+```
+
+  
+
+
+8) Run the application:
 
 ```bash
 ./sheetjs-hermes pres.numbers
@@ -663,7 +686,7 @@ contents of the first sheet as CSV rows.
 
 :::note Tested Deployments
 
-This demo was last tested on 2023 November 04 against Hermes version `0.11.0`.
+This demo was last tested on 2023 November 04 against Hermes version `0.12.0`.
 
 :::
 
@@ -675,7 +698,7 @@ as a Base64 string and directly add it to an amalgamated script.
 0) Install the Hermes command line tools:
 
 ```bash
-npx jsvu install hermes@0.11.0
+npx jsvu hermes@0.12.0
 ```
 
 When prompted, select the appropriate operating system.
@@ -685,10 +708,10 @@ When prompted, select the appropriate operating system.
 ```text pass
 ❯ Extracting…
 // highlight-next-line
-Installing binary to ~/.jsvu/engines/hermes-0.11.0/hermes-0.11.0…
-Installing symlink at ~/.jsvu/bin/hermes-0.11.0 pointing to ~/.jsvu/engines/hermes-0.11.0/hermes-0.11.0…
-Installing binary to ~/.jsvu/engines/hermes-0.11.0/hermes-0.11.0-compiler…
-Installing symlink at ~/.jsvu/bin/hermes-0.11.0-compiler pointing to ~/.jsvu/engines/hermes-0.11.0/hermes-0.11.0-compiler…
+Installing binary to ~/.jsvu/engines/hermes-0.12.0/hermes-0.12.0…
+Installing symlink at ~/.jsvu/bin/hermes-0.12.0 pointing to ~/.jsvu/engines/hermes-0.12.0/hermes-0.12.0…
+Installing binary to ~/.jsvu/engines/hermes-0.12.0/hermes-0.12.0-compiler…
+Installing symlink at ~/.jsvu/bin/hermes-0.12.0-compiler pointing to ~/.jsvu/engines/hermes-0.12.0/hermes-0.12.0-compiler…
 ```
 
 The first "Installing binary" line mentions the path to the `hermes` tool.
@@ -705,7 +728,7 @@ cd sheetjs-hermes-cli
 3) Copy the binary from Step 1 into the current folder. For example, on macOS:
 
 ```bash
-cp ~/.jsvu/engines/hermes-0.11.0/hermes-0.11.0 .
+cp ~/.jsvu/engines/hermes-0.12.0/hermes-0.12.0 .
 ```
 
 #### Create Script
@@ -759,7 +782,7 @@ ready, it will read the bundled test data and print the contents as CSV.
 8) Run the script using the Hermes standalone binary:
 
 ```bash
-./hermes-0.11.0 sheetjs.hermes.js
+./hermes-0.12.0 sheetjs.hermes.js
 ```
 
 If successful, the script will print CSV data from the test file.
diff --git a/docz/docs/03-demos/42-engines/15-rb.md b/docz/docs/03-demos/42-engines/15-rb.md
index 405ecf6..075bfc4 100644
--- a/docz/docs/03-demos/42-engines/15-rb.md
+++ b/docz/docs/03-demos/42-engines/15-rb.md
@@ -74,7 +74,7 @@ This demo was tested in the following deployments:
 | `darwin-arm` | `2.6.10` | `2.9.1` | 2023-12-01 |
 | `win10-x64`  | `3.2.2`  | `2.9.1` | 2023-10-28 |
 | `win11-arm`  | `3.0.2`  | `2.9.1` | 2023-12-01 |
-| `linux-x64`  | `3.0.4`  | `2.9.1` | 2023-10-11 |
+| `linux-x64`  | `3.0.5`  | `2.9.1` | 2024-01-26 |
 | `linux-arm`  | `2.7.4`  | `2.9.1` | 2023-12-01 |
 
 **Note: The Windows 11 ARM64 test used the Ruby version that ships with WSL.**
diff --git a/docz/docs/03-demos/42-engines/20-chakra.md b/docz/docs/03-demos/42-engines/20-chakra.md
index 902c635..1fff777 100644
--- a/docz/docs/03-demos/42-engines/20-chakra.md
+++ b/docz/docs/03-demos/42-engines/20-chakra.md
@@ -135,7 +135,7 @@ This demo was tested in the following deployments:
 | `darwin-x64` | `c3ead3f`  | 2023-11-04 |
 | `darwin-arm` | `c3ead3f`  | 2023-10-19 |
 | `win10-x64`  | `c3ead3f`  | 2023-10-28 |
-| `linux-x64`  | `c3ead3f`  | 2023-12-09 |
+| `linux-x64`  | `c3ead3f`  | 2024-01-26 |
 
 :::
 
diff --git a/docz/docs/03-demos/42-engines/21-boa.md b/docz/docs/03-demos/42-engines/21-boa.md
index 9318d90..1d4ada7 100644
--- a/docz/docs/03-demos/42-engines/21-boa.md
+++ b/docz/docs/03-demos/42-engines/21-boa.md
@@ -124,7 +124,7 @@ This demo was tested in the following deployments:
 | `darwin-arm` | 2023-10-20 |
 | `win10-x64`  | 2023-10-28 |
 | `win11-arm`  | 2023-12-01 |
-| `linux-x64`  | 2023-12-07 |
+| `linux-x64`  | 2024-01-26 |
 | `linux-arm`  | 2023-12-01 |
 
 :::
diff --git a/docz/docs/03-demos/42-engines/23-jerryscript.md b/docz/docs/03-demos/42-engines/23-jerryscript.md
index ba7aa3d..7af470c 100644
--- a/docz/docs/03-demos/42-engines/23-jerryscript.md
+++ b/docz/docs/03-demos/42-engines/23-jerryscript.md
@@ -40,13 +40,11 @@ This demo was tested in the following environments:
 | `darwin-arm` | `ef4cb2b` | 2023-12-08 |
 | `win11-x64`  | `ef4cb2b` | 2023-12-08 |
 | `win11-arm`  | `ef4cb2b` | 2023-12-08 |
-| `linux-x64`  | `ef4cb2b` | 2023-12-08 |
+| `linux-x64`  | `514fa67` | 2024-01-26 |
 | `linux-arm`  | `ef4cb2b` | 2023-12-08 |
 
 The Windows tests were run in WSL.
 
-Debian and WSL require the `cmake`, `python3` and `python-is-python3` packages.
-
 :::
 
 ## Integration Details
@@ -343,6 +341,14 @@ while the "CLI Test" demonstrates other concepts using the `jerry` CLI tool.
 
 ### Integration Example
 
+Build Dependencies (click to show)
+
+The JerryScript build system requires `cmake`.
+
+Debian and WSL additionally require `python3` and `python-is-python3` packages.
+
+