diff --git a/docz/docs/03-demos/02-mobile.md b/docz/docs/03-demos/02-mobile.md
index a924cdb..2be4064 100644
--- a/docz/docs/03-demos/02-mobile.md
+++ b/docz/docs/03-demos/02-mobile.md
@@ -1517,4 +1517,188 @@ curl -o src/app/home/home.page.ts -L https://docs.sheetjs.com/ionic/home.page.ts
 npx @ionic/cli cordova emulate ios
 ```
 
+</details>
+
+## CapacitorJS
+
+:::note
+
+This demo was tested on an Intel Mac on 2022 August 26 with Svelte.
+
+The iOS simulator runs iOS 15.5 on an iPhone 13 Pro Max.
+
+:::
+
+:::warning Telemetry
+
+Before starting this demo, manually disable telemetry.  On Linux and MacOS:
+
+```bash
+npx @capacitor/cli telemetry off
+```
+
+To verify telemetry was disabled:
+
+```bash
+npx @capacitor/cli telemetry
+```
+
+:::
+
+### Integration Details
+
+This example uses Svelte, but the same principles apply to other frameworks.
+
+#### Reading data
+
+The standard HTML5 File Input element logic works in CapacitorJS:
+
+```html
+<script>
+import { read, utils } from 'xlsx';
+
+let html = "";
+
+/* show file picker, read file, load table */
+async function importFile(evt) {
+  // highlight-start
+  const f = evt.target.files[0];
+  const wb = read(await f.arrayBuffer());
+  // highlight-end
+  const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
+  html = utils.sheet_to_html(ws); // generate HTML and update state
+}
+</script>
+
+<main>
+  <!-- highlight-next-line -->
+  <input type="file" on:change={importFile}/>
+  <div bind:this={tbl}>{@html html}</div>
+</main>
+```
+
+#### Writing data
+
+`@capacitor/fileysstem` can write Base64 strings:
+
+```html
+<script>
+import { Filesystem, Directory } from '@capacitor/filesystem';
+import { utils, writeXLSX } from 'xlsx';
+
+let html = "";
+let tbl;
+
+/* get state data and export to XLSX */
+async function exportFile() {
+  const elt = tbl.getElementsByTagName("TABLE")[0];
+  const wb = utils.table_to_book(elt);
+  /* generate Base64 string for Capacitor */
+  // highlight-start
+  const data = writeXLSX(wb, { type: "base64" });
+  await Filesystem.writeFile({
+    data,
+    path: "SheetJSCap.xlsx",
+    directory: Directory.Documents
+  }); // write file
+  // highlight-end
+}
+
+</script>
+
+<main>
+  <button on:click={exportFile}>Export XLSX</button>
+  <div bind:this={tbl}>{@html html}</div>
+</main>
+```
+
+### Demo
+
+<details><summary><b>Complete Example</b> (click to show)</summary>
+
+0) Disable telemetry as noted in the warning.
+
+Follow the [React Native demo](#demo) to ensure iOS and Android sims are ready.
+
+
+1) Create a new Svelte project:
+
+```bash
+npm create vite@latest sheetjs-cap -- --template svelte
+cd sheetjs-cap
+```
+
+2) Install dependencies:
+
+```bash
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
+npm i --save @capacitor/core @capacitor/cli @capacitor/ios @capacitor/filesystem
+```
+
+3) Create CapacitorJS structure:
+
+```bash
+npx cap init sheetjs-cap com.sheetjs.cap --web-dir=dist
+npx cap add ios
+```
+
+4) Replace the contents of `src/App.svelte` with the following:
+
+```html title="src/App.svelte"
+<script>
+import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
+import { onMount } from 'svelte';
+import { read, utils, version, writeXLSX } from 'xlsx';
+
+let html = "";
+let tbl;
+
+/* Fetch and update the state once */
+onMount(async() => {
+  const f = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
+  const wb = read(f); // parse the array buffer
+  const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
+  html = utils.sheet_to_html(ws); // generate HTML and update state
+});
+
+/* get state data and export to XLSX */
+async function exportFile() {
+  const elt = tbl.getElementsByTagName("TABLE")[0];
+  const wb = utils.table_to_book(elt);
+  /* generate Base64 string for Capacitor */
+  const data = writeXLSX(wb, { type: "base64" });
+  /* write */
+  await Filesystem.writeFile({
+    path: "SheetJSCap.xlsx",
+    data,
+    directory: Directory.Documents
+  });
+}
+
+/* show file picker, read file, load table */
+async function importFile(evt) {
+  const f = evt.target.files[0];
+  const wb = read(await f.arrayBuffer());
+  const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
+  html = utils.sheet_to_html(ws); // generate HTML and update state
+}
+</script>
+
+<main>
+  <h3>SheetJS × CapacitorJS { version }</h3>
+  <input type="file" on:change={importFile}/>
+  <button on:click={exportFile}>Export XLSX</button>
+  <div bind:this={tbl}>{@html html}</div>
+</main>
+```
+
+5) Test the app:
+
+```bash
+npm run build; npx cap sync; npx cap run ios
+```
+
+There are 3 steps: build the Svelte app, sync with CapacitorJS, and run sim.
+This sequence must be run every time to ensure changes are propagated.
+
 </details>
\ No newline at end of file
diff --git a/docz/docs/03-demos/14-svelte.md b/docz/docs/03-demos/14-svelte.md
index a40892f..421b973 100644
--- a/docz/docs/03-demos/14-svelte.md
+++ b/docz/docs/03-demos/14-svelte.md
@@ -7,6 +7,10 @@ title: Svelte
 This demo tries to cover common Svelte data flow ideas and strategies. Svelte
 familiarity is assumed.
 
+Other demos cover general React deployments, including:
+
+- [iOS applications powered by CapacitorJS](./mobile#capacitorjs)
+
 
 ## Installation