diff --git a/docz/docs/03-demos/01-frontend/19-bundler/04-esbuild.md b/docz/docs/03-demos/01-frontend/19-bundler/04-esbuild.md
new file mode 100644
index 0000000..2cc331c
--- /dev/null
+++ b/docz/docs/03-demos/01-frontend/19-bundler/04-esbuild.md
@@ -0,0 +1,217 @@
+---
+title: Bundling Sheets with ESBuild
+sidebar_label: ESBuild
+pagination_prev: demos/index
+pagination_next: demos/grid/index
+sidebar_position: 4
+---
+
+import current from '/version.js';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import CodeBlock from '@theme/CodeBlock';
+
+[ESBuild](https://esbuild.github.io/) is a fast module bundler for JavaScript.
+It combines scripts and libraries into simple scripts for browsers and NodeJS.
+
+[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
+data from spreadsheets.
+
+This demo uses ESBuild and SheetJS to export data. We'll explore two workflows:
+
+- ["Browser"](#browser) explores how to import SheetJS libraries in a script and
+bundle with ESBuild for browser use.
+
+- ["NodeJS"](#nodejs) explores how to import SheetJS libraries in a script and
+bundle with ESBuild for NodeJS use.
+
+:::info pass
+
+This demo focuses on integration details with the ESBuild bundler.
+
+The demos follow the ["Export Tutorial"](/docs/getting-started/examples/export).
+The tutorial covers SheetJS library usage.
+
+:::
+
+:::note
+
+This demo was last tested on 2023 October 19 against esbuild `0.19.5`
+
+:::
+
+## Integration Details
+
+[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
+installation with Yarn and other package managers.
+
+## Browser
+
+ESBuild will bundle the SheetJS ECMAScript Module build:
+
+```js
+import { read, utils, writeFileXLSX } from 'xlsx';
+```
+
+:::note pass
+
+The `xlsx.mjs` source file uses a subset of ES6 that `esbuild` understands and
+is able to transpile for older browsers.
+
+:::
+
+Assuming the primary source file is `in.js`, the following command will bundle
+the script and generate `out.js`:
+
+```bash
+npx -y esbuild@0.19.5 in.js --bundle --outfile=out.js
+```
+
+### Browser Demo
+
+0) Prepare a blank project:
+
+```bash
+mkdir sheetjs-esbrowser
+cd sheetjs-esbrowser
+npm init -y
+```
+
+1) Install the tarball using a package manager:
+
+
+
+{`\
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+{`\
+pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+{`\
+yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+
+2) Download [`esbrowser.js`](pathname:///esbuild/esbrowser.js) and move to the
+project folder:
+
+```bash
+curl -LO https://docs.sheetjs.com/esbuild/esbrowser.js
+```
+
+3) Create a small HTML page that loads the script. Save to `index.html`:
+
+```html title="index.html"
+
+```
+
+4) Create bundle:
+
+```bash
+npx -y esbuild@0.19.5 esbrowser.js --bundle --outfile=esb.browser.js
+```
+
+5) Start a local HTTP server:
+
+```bash
+npx http-server .
+```
+
+Access the displayed URL (typically `http://localhost:8080`) with a web browser.
+It should attempt to download `Presidents.xlsx`
+
+## NodeJS
+
+ESBuild will bundle the SheetJS ECMAScript Module build:
+
+```js
+import { read, utils, write } from 'xlsx';
+```
+
+:::caution pass
+
+To read and write files on the local filesystem using the SheetJS `readFile` and
+`writeFile` methods[^1], the `fs` module must be manually added:
+
+```js
+import { set_fs, readFile } from 'xlsx';
+import * as fs from 'fs';
+set_fs(fs);
+
+/* read pres.numbers in the same directory as the script */
+const wb = readFile("pres.numbers");
+```
+
+:::
+
+Assuming the primary source file is `in.js`, the following command will bundle
+the script for NodeJS and generate `out.js`:
+
+```bash
+npx -y esbuild@0.19.5 in.js --bundle --platform=node --outfile=out.js
+```
+
+### NodeJS Demo
+
+:::info pass
+
+This demo script uses `fetch` and requires Node 18+.
+
+:::
+
+0) Prepare a blank project:
+
+```bash
+mkdir sheetjs-esbnode
+cd sheetjs-esbnode
+npm init -y
+```
+
+1) Install the tarball using a package manager:
+
+
+
+{`\
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+{`\
+pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+{`\
+yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+
+
+2) Download [`esbnode.js`](pathname:///esbuild/esbnode.js) and move to the
+project folder:
+
+```bash
+curl -LO https://docs.sheetjs.com/esbuild/esbnode.js
+```
+
+3) Create bundle:
+
+```bash
+npx -y esbuild@0.19.5 esbnode.js --bundle --platform=node --outfile=esb.node.js
+```
+
+4) Run the bundle:
+
+```bash
+node esb.node.js
+```
+
+The process will generate `Presidents.xlsx` in the project directory. Open the
+file in a spreadsheet editor.
+
+[^1]: The SheetJS [`readFile`](/docs/api/parse-options) and [`writeFile`](/docs/api/write-options) methods use the NodeJS `fs` module when available. It is not automatically loaded in the ECMAScript Module builds.
\ No newline at end of file
diff --git a/docz/docs/03-demos/01-frontend/19-bundler/12-systemjs.md b/docz/docs/03-demos/01-frontend/19-bundler/12-systemjs.md
index c6b4e1a..78c0429 100644
--- a/docz/docs/03-demos/01-frontend/19-bundler/12-systemjs.md
+++ b/docz/docs/03-demos/01-frontend/19-bundler/12-systemjs.md
@@ -111,7 +111,9 @@ _cb = function(evt) { /* ... do work here ... */ };
:::caution pass
-While SystemJS works in NodeJS, the built-in `require` should be preferred.
+**It is strongly recommended to use the NodeJS `require` method when possible.**
+
+This demo is relevant for legacy projects that use the SystemJS NodeJS loader.
:::
diff --git a/docz/docs/03-demos/01-frontend/19-bundler/index.md b/docz/docs/03-demos/01-frontend/19-bundler/index.md
index c64a92b..d6e9d0c 100644
--- a/docz/docs/03-demos/01-frontend/19-bundler/index.md
+++ b/docz/docs/03-demos/01-frontend/19-bundler/index.md
@@ -209,187 +209,9 @@ Integration details are included [in the "AMD" installation](/docs/getting-start
Complete Examples are included [in the "Dojo" demo](/docs/demos/frontend/legacy#dojo-toolkit)
+#### esbuild
-## esbuild
-
-The `xlsx.mjs` source file uses a subset of ES6 that `esbuild` understands and
-is able to transpile for older browsers.
-
-Both the `node` and `browser` platforms work out of the box.
-
-Complete Example (click to show)
-
-:::note
-
-This demo was last tested on 2023 May 07 against esbuild `0.17.18`
-
-:::
-
-
-
-
-1) Install the tarball using a package manager:
-
-
-
-{`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-{`\
-pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-{`\
-yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-
-2) Save the following to `esbrowser.js`:
-
-```js title="esbrowser.js"
-// highlight-next-line
-import { utils, version, writeFileXLSX } from 'xlsx';
-
-(async() => {
-/* fetch JSON data and parse */
-const url = "https://sheetjs.com/data/executive.json";
-const raw_data = await (await fetch(url)).json();
-
-/* filter for the Presidents */
-const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
-
-/* flatten objects */
-const rows = prez.map(row => ({
- name: row.name.first + " " + row.name.last,
- birthday: row.bio.birthday
-}));
-
-/* generate worksheet and workbook */
-const worksheet = utils.json_to_sheet(rows);
-const workbook = utils.book_new();
-utils.book_append_sheet(workbook, worksheet, "Dates");
-
-/* fix headers */
-utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
-
-/* calculate column width */
-const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
-worksheet["!cols"] = [ { wch: max_width } ];
-
-/* create an XLSX file and try to save to Presidents.xlsx */
-writeFileXLSX(workbook, "Presidents.xlsx");
-})();
-```
-
-3) Create a small HTML page that loads the script. Save to `index.html`:
-
-```html title="index.html"
-
-```
-
-4) Create bundle:
-
-```bash
-npx esbuild@0.17.18 esbrowser.js --bundle --outfile=esb.browser.js
-```
-
-5) Start a local HTTP server, then go to `http://localhost:8080/`
-
-```bash
-npx http-server .
-```
-
-
-
-
-1) Install the tarball using a package manager:
-
-
-
-{`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-{`\
-pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-{`\
-yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
-
-
-
-
-2) Save the following to `esbnode.js`:
-
-```js title="esbnode.js"
-// highlight-next-line
-import { set_fs, utils, version, writeFile } from 'xlsx';
-// highlight-next-line
-import * as fs from 'fs';
-// highlight-next-line
-set_fs(fs);
-
-(async() => {
-/* fetch JSON data and parse */
-const url = "https://sheetjs.com/data/executive.json";
-const raw_data = await (await fetch(url)).json();
-
-/* filter for the Presidents */
-const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
-
-/* flatten objects */
-const rows = prez.map(row => ({
- name: row.name.first + " " + row.name.last,
- birthday: row.bio.birthday
-}));
-
-/* generate worksheet and workbook */
-const worksheet = utils.json_to_sheet(rows);
-const workbook = utils.book_new();
-utils.book_append_sheet(workbook, worksheet, "Dates");
-
-/* fix headers */
-utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
-
-/* calculate column width */
-const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
-worksheet["!cols"] = [ { wch: max_width } ];
-
-/* create an XLSX file and try to save to Presidents.xlsx */
-writeFile(workbook, "Presidents.xlsx");
-})();
-```
-
-3) Create bundle:
-
-```bash
-npx esbuild@0.17.18 esbnode.js --bundle --platform=node --outfile=esb.node.js
-```
-
-4) Run the bundle:
-
-```bash
-node esb.node.js
-```
-
-
-
-
-
-
-:::note pass
-
-Bundling raw data is supported using the `binary` loader. For more advanced
-content workflows, [ViteJS](/docs/demos/static/vitejs) is the recommended tool.
-
-:::
+**[The exposition has been moved to a separate page.](/docs/demos/frontend/bundler/esbuild)**
## Parcel
diff --git a/docz/docs/03-demos/42-engines/20-chakra.md b/docz/docs/03-demos/42-engines/20-chakra.md
index c92707d..63e04e8 100644
--- a/docz/docs/03-demos/42-engines/20-chakra.md
+++ b/docz/docs/03-demos/42-engines/20-chakra.md
@@ -121,7 +121,7 @@ This demo was tested in the following deployments:
| Architecture | Git Commit | Date |
|:-------------|:-----------|:-----------|
| `darwin-x64` | `c3ead3f` | 2023-08-26 |
-| `darwin-arm` | `c3ead3f` | 2023-08-26 |
+| `darwin-arm` | `c3ead3f` | 2023-10-19 |
| `win10-x64` | `c3ead3f` | 2023-08-26 |
| `linux-x64` | `c3ead3f` | 2023-10-11 |
@@ -308,10 +308,9 @@ clang: error: no such file or directory: '/usr/local/opt/icu4c/lib/libicudata.a'
This was fixed by creating a symbolic link:
```bash
-cd /usr/local
-sudo mkdir -p opt
-cd opt
-sudo ln -s /opt/homebrew/opt/icu4c
+sudo mkdir -p /usr/local/opt
+sudo ln -s /opt/homebrew/opt/icu4c /usr/local/opt
+make
```
:::
diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md
index 211c92c..11a0b76 100644
--- a/docz/docs/03-demos/index.md
+++ b/docz/docs/03-demos/index.md
@@ -118,7 +118,7 @@ in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues)
- [`browserify`](/docs/demos/frontend/bundler#browserify)
- [`bun`](/docs/demos/frontend/bundler#bun)
-- [`esbuild`](/docs/demos/frontend/bundler#esbuild)
+- [`esbuild`](/docs/demos/frontend/bundler/esbuild)
- [`parcel`](/docs/demos/frontend/bundler#parcel)
- [`requirejs`](/docs/demos/frontend/bundler/requirejs)
- [`rollup`](/docs/demos/frontend/bundler#rollup)
diff --git a/docz/static/esbuild/esbnode.js b/docz/static/esbuild/esbnode.js
new file mode 100644
index 0000000..4b76880
--- /dev/null
+++ b/docz/static/esbuild/esbnode.js
@@ -0,0 +1,37 @@
+import { set_fs, utils, writeFile } from 'xlsx';
+import * as fs from 'fs';
+set_fs(fs);
+
+(async() => {
+/* fetch JSON data and parse */
+const url = "https://sheetjs.com/data/executive.json";
+const raw_data = await (await fetch(url)).json();
+
+/* filter for the Presidents */
+const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+
+/* sort by first presidential term */
+prez.forEach(row => row.start = row.terms.find(term => term.type === "prez").start);
+prez.sort((l,r) => l.start.localeCompare(r.start));
+
+/* flatten objects */
+const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+}));
+
+/* generate worksheet and workbook */
+const worksheet = utils.json_to_sheet(rows);
+const workbook = utils.book_new();
+utils.book_append_sheet(workbook, worksheet, "Dates");
+
+/* fix headers */
+utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+
+/* calculate column width */
+const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+worksheet["!cols"] = [ { wch: max_width } ];
+
+/* create an XLSX file and try to save to Presidents.xlsx */
+writeFile(workbook, "Presidents.xlsx");
+})();
\ No newline at end of file
diff --git a/docz/static/esbuild/esbrowser.js b/docz/static/esbuild/esbrowser.js
new file mode 100644
index 0000000..ae3b2e7
--- /dev/null
+++ b/docz/static/esbuild/esbrowser.js
@@ -0,0 +1,35 @@
+import { utils, writeFileXLSX } from 'xlsx';
+
+(async() => {
+/* fetch JSON data and parse */
+const url = "https://sheetjs.com/data/executive.json";
+const raw_data = await (await fetch(url)).json();
+
+/* filter for the Presidents */
+const prez = raw_data.filter(row => row.terms.some(term => term.type === "prez"));
+
+/* sort by first presidential term */
+prez.forEach(row => row.start = row.terms.find(term => term.type === "prez").start);
+prez.sort((l,r) => l.start.localeCompare(r.start));
+
+/* flatten objects */
+const rows = prez.map(row => ({
+ name: row.name.first + " " + row.name.last,
+ birthday: row.bio.birthday
+}));
+
+/* generate worksheet and workbook */
+const worksheet = utils.json_to_sheet(rows);
+const workbook = utils.book_new();
+utils.book_append_sheet(workbook, worksheet, "Dates");
+
+/* fix headers */
+utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
+
+/* calculate column width */
+const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
+worksheet["!cols"] = [ { wch: max_width } ];
+
+/* create an XLSX file and try to save to Presidents.xlsx */
+writeFileXLSX(workbook, "Presidents.xlsx");
+})();
\ No newline at end of file