diff --git a/docz/docs/03-demos/05-mobile/03-quasar.md b/docz/docs/03-demos/05-mobile/03-quasar.md
index ea54dc7..68b4d7f 100644
--- a/docz/docs/03-demos/05-mobile/03-quasar.md
+++ b/docz/docs/03-demos/05-mobile/03-quasar.md
@@ -10,10 +10,25 @@ sidebar_custom_props:
 The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
 from the main entrypoint or any script in the project.
 
-This demo will use the Quasar ViteJS starter project with VueJS and Cordova.
+The "Complete Example" creates an app that looks like the screenshots below:
+
+<table><thead><tr>
+  <th><a href="#demo">iOS</a></th>
+  <th><a href="#demo">Android</a></th>
+</tr></thead><tbody><tr><td>
+
+![iOS screenshot](pathname:///quasar/ios.png)
+
+</td><td>
+
+![Android screenshot](pathname:///quasar/and.png)
+
+</td></tr></tbody></table>
 
 ### Integration Details
 
+This demo will use the Quasar ViteJS starter project with VueJS and Cordova.
+
 The complete solution uses `cordova-plugin-file` for file operations.  It can
 be installed like any other Cordova plugin:
 
@@ -89,16 +104,18 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
 
 :::note
 
-This demo was tested on an Intel Mac on 2022 August 14. Quasar version `2.7.7`.
-The iOS simulator runs iOS 15.5 on an iPhone SE 3rd generation.
+This demo was tested on an Intel Mac on 2023 April 08. `create-quasar@1.1.2`
+was installed during app creation.  The app used Quasar version `2.11.10`.
+
+The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
+
+The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
 
 :::
 
 The demo draws from the ViteJS example.  Familiarity with VueJS and TypeScript
 is assumed.
 
-<details><summary><b>Complete Example</b> (click to show)</summary>
-
 0) Ensure all of the dependencies are installed.  Install the CLI globally:
 
 ```bash
@@ -189,28 +206,31 @@ then restart the development process.
 
 :::
 
-![Quasar Step 4](pathname:///mobile/quasar4.png)
-
-
 5) Add the Dialog plugin to `quasar.config.js`:
 
 ```js title="quasar.config.js"
+    framework: {
+      config: {},
+// ...
       // Quasar plugins
       // highlight-next-line
       plugins: ['Dialog']
+    },
 ```
 
-6) In the template section of `src/pages/IndexPage.vue`, add a Save button and
-   a Load file picker component at the bottom of the page:
+6) In the template section of `src/pages/IndexPage.vue`, replace the example
+   with a Table, Save button and Load file picker component:
 
 ```html title="src/pages/IndexPage.vue"
+<template>
+  <q-page class="row items-center justify-evenly">
     <!-- highlight-start -->
+    <q-table :rows="todos" />
     <q-btn-group>
       <q-file label="Load File" filled label-color="orange" @input="updateFile"/>
       <q-btn label="Save File" @click="saveFile" />
     </q-btn-group>
-    <!-- highlight-end -->
-  </q-page>
+    <!-- highlight-end -->  </q-page>
 </template>
 ```
 
@@ -223,7 +243,7 @@ This uses two functions that should be added to the component script:
 // highlight-start
     function saveFile() {
     }
-    async function updateFile(v) {
+    async function updateFile(v: Event) {
     }
     return { todos, meta, saveFile, updateFile };
 // highlight-end
@@ -256,11 +276,11 @@ export default defineComponent({
 // ...
 // highlight-start
     const $q = useQuasar();
-    function dialogerr(e) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
+    function dialogerr(e: Error) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
 // highlight-end
     function saveFile() {
     }
-    async function updateFile(v) {
+    async function updateFile(v: Event) {
 // highlight-start
       try {
         const files = (v.target as HTMLInputElement).files;
@@ -268,7 +288,7 @@ export default defineComponent({
 
         const wb = read(await files[0].arrayBuffer());
 
-        const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
+        const data = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]]);
         todos.value = data.map(row => ({id: row.Index, content: row.Name}));
       } catch(e) { dialogerr(e); }
 // highlight-end
@@ -290,13 +310,11 @@ To test that reading works:
 
 ![Quasar Step 7 load file](pathname:///mobile/quasar7b.png)
 
-Once selected, the screen should refresh with new contents:
-
-![Quasar Step 7 new data](pathname:///mobile/quasar7c.png)
+Once selected, the screen should refresh with new contents.
 
 8) Wire up the `saveFile` function:
 
-```js
+```ts title="src/pages/IndexPage.vue"
     function saveFile() {
 // highlight-start
       /* generate workbook from state */
@@ -304,12 +322,13 @@ Once selected, the screen should refresh with new contents:
       const wb = utils.book_new();
       utils.book_append_sheet(wb, ws, "SheetJSQuasar");
       const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"});
+      const dir: string = $q.cordova.file.documentsDirectory || $q.cordova.file.externalApplicationStorageDirectory;
 
       /* save to file */
       window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
         try {
           fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => {
-            const msg = `File stored at ${$q.cordova.file.documentsDirectory} ${entry.fullPath}`;
+            const msg = `File stored at ${dir} ${entry.fullPath}`;
             entry.createWriter(writer => {
               try {
                 const data = new Blob([u8], {type: "application/vnd.ms-excel"});
@@ -377,5 +396,46 @@ id,content
 46,Joseph Biden
 ```
 
-</details>
+**Android**
 
+9) Create the Android project:
+
+```bash
+cd src-cordova
+cordova platform add android
+cd ..
+```
+
+10) Start the simulator:
+
+```bash
+quasar dev -m android
+```
+
+:::note
+
+In local testing, the Quasar build process threw an error:
+
+```
+  java.lang.IllegalArgumentException: Unsupported class file major version 63
+```
+
+This was resolved by rolling back to Java 1.8
+
+:::
+
+To test that reading works:
+
+- Click and drag `pres.numbers` from a Finder window into the simulator.
+- Tap "Load", tap the `≡` icon, tap "Downloads" and select `pres.numbers`.
+
+To test that writing works:
+
+- Tap "Save File".  You will see a popup with a location.
+
+- Pull the file from the simulator and verify the contents:
+
+```bash
+adb exec-out run-as org.sheetjs.quasar cat files/files/SheetJSQuasar.xlsx > /tmp/SheetJSQuasar.xlsx
+npx xlsx-cli /tmp/SheetJSQuasar.xlsx
+```
diff --git a/docz/docs/03-demos/05-mobile/04-ionic.md b/docz/docs/03-demos/05-mobile/04-ionic.md
index a0e81fd..8455293 100644
--- a/docz/docs/03-demos/05-mobile/04-ionic.md
+++ b/docz/docs/03-demos/05-mobile/04-ionic.md
@@ -107,7 +107,7 @@ this.file.writeFile(url, filename, blob, {replace: true});
 This demo was tested on an Intel Mac on 2023 March 28 with Cordova.
 The file integration uses `@ionic-native/file` version `5.36.0`.
 
-The iOS simulator runs iOS 16.5 on an iPhone SE (3rd Generation).
+The iOS simulator runs iOS 15.5 on an iPhone SE (3rd Generation).
 
 The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
 
diff --git a/docz/static/quasar/and.png b/docz/static/quasar/and.png
new file mode 100644
index 0000000..043b5aa
Binary files /dev/null and b/docz/static/quasar/and.png differ
diff --git a/docz/static/quasar/ios.png b/docz/static/quasar/ios.png
new file mode 100644
index 0000000..b15e75f
Binary files /dev/null and b/docz/static/quasar/ios.png differ