diff --git a/docz/docs/03-demos/20-content.md b/docz/docs/03-demos/20-content.md
index 64f91f8..8eca7ca 100644
--- a/docz/docs/03-demos/20-content.md
+++ b/docz/docs/03-demos/20-content.md
@@ -21,6 +21,310 @@ in the parsing logic, issues should then be raised with the SheetJS project.
:::
+## NextJS
+
+:::note
+
+This was tested against `next v12.2.5` on 2022 August 16.
+
+:::
+
+:::caution
+
+At a high level, there are two ways to pull spreadsheet data into NextJS apps:
+loading an asset module or performing the file read operations from the NextJS
+lifecycle. At the time of writing, NextJS does not offer an out-of-the-box
+asset module solution, so this demo focuses on raw operations. NextJS does not
+watch the spreadsheets, so `next dev` hot reloading will not work!
+
+:::
+
+The general strategy with NextJS apps is to generate HTML snippets or data from
+the lifecycle functions and reference them in the template.
+
+HTML output can be generated using `XLSX.utils.sheet_to_html` and inserted into
+the document using the `dangerouslySetInnerHTML` attribute:
+
+```jsx
+export default function Index({html, type}) { return (
+ // ...
+// highlight-next-line
+
+ // ...
+); }
+```
+
+:::warning
+
+`fs` cannot be statically imported from the top level in NextJS pages. The
+dynamic import must happen within a lifecycle function. For example:
+
+```js
+/* it is safe to import the library from the top level */
+import { readFile, utils, set_fs } from 'xlsx';
+/* it is not safe to import 'fs' from the top level ! */
+// import * as fs from 'fs'; // this will fail
+import { join } from 'path';
+import { cwd } from 'process';
+
+export async function getServerSideProps() {
+// highlight-next-line
+ set_fs(await import("fs")); // dynamically import 'fs' when needed
+ const wb = readFile(join(cwd(), "public", "sheetjs.xlsx")); // works
+ // ...
+}
+```
+
+
+
+:::
+
+### Strategies
+
+#### "Static Site Generation" using `getStaticProps`
+
+When using `getStaticProps`, the file will be read once during build time.
+
+```js
+import { readFile, set_fs, utils } from 'xlsx';
+
+export async function getStaticProps() {
+ /* read file */
+ set_fs(await import("fs"));
+ const wb = readFile(path_to_file)
+
+ /* generate and return the html from the first worksheet */
+ const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
+ return { props: { html } };
+};
+```
+
+#### "Static Site Generation with Dynamic Routes" using `getStaticPaths`
+
+Typically a static site with dynamic routes has an endpoint `/sheets/[id]` that
+implements both `getStaticPaths` and `getStaticProps`.
+
+- `getStaticPaths` should return an array of worksheet indices:
+
+```js
+export async function getStaticPaths() {
+ /* read file */
+ set_fs(await import("fs"));
+ const wb = readFile(path);
+
+ /* generate an array of objects that will be used for generating pages */
+ const paths = wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString() } }));
+ return { paths, fallback: false };
+};
+```
+
+:::note
+
+For a pure static site, `fallback` must be set to `false`!
+
+:::
+
+- `getStaticProps` will generate the actual HTML for each page:
+
+```js
+export async function getStaticProps(ctx) {
+ /* read file */
+ set_fs(await import("fs"));
+ const wb = readFile(path);
+
+ /* get the corresponding worksheet and generate HTML */
+ const ws = wb.Sheets[wb.SheetNames[ctx.params.id]]; // id from getStaticPaths
+ const html = utils.sheet_to_html(ws);
+ return { props: { html } };
+};
+```
+
+#### "Server-Side Rendering" using `getServerSideProps`
+
+:::caution Do not use on a static site
+
+These routes require a NodeJS dynamic server. Static page generation will fail!
+
+`getStaticProps` and `getStaticPaths` support SSG.
+
+`getServerSideProps` is suited for NodeJS hosted deployments where the workbook
+changes frequently and a static site is undesirable.
+
+:::
+
+When using `getServerSideProps`, the file will be read on each request.
+
+```js
+import { readFile, set_fs, utils } from 'xlsx';
+
+export async function getServerSideProps() {
+ /* read file */
+ set_fs(await import("fs"));
+ const wb = readFile(path_to_file);
+
+ /* generate and return the html from the first worksheet */
+ const html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
+ return { props: { html } };
+};
+```
+
+### Demo
+
+Complete Example (click to show)
+
+0) Disable NextJS telemetry:
+
+```js
+npx next telemetry disable
+```
+
+Confirm it is disabled by running
+
+```js
+npx next telemetry status
+```
+
+1) Set up folder structure. At the end, a `pages` folder with a `sheets`
+ subfolder must be created. On Linux or macOS or WSL:
+
+```bash
+mkdir -p pages/sheets/
+```
+
+2) Download the [test file](pathname:///next/sheetjs.xlsx) and place in the
+ project root. On Linux or macOS or WSL:
+
+```bash
+curl -LO https://docs.sheetjs.com/next/sheetjs.xlsx
+```
+
+3) Install dependencies:
+
+```bash
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz next
+```
+
+4) Download test scripts:
+
+Download and place the following scripts in the `pages` subdirectory:
+
+- [`index.js`](pathname:///next/index.js)
+- [`getServerSideProps.js`](pathname:///next/getServerSideProps.js)
+- [`getStaticPaths.js`](pathname:///next/getStaticPaths.js)
+- [`getStaticProps.js`](pathname:///next/getStaticProps.js)
+
+Download [`[id].js`](pathname:///next/%5Bid%5D.js) and place in the
+`pages/sheets` subdirectory.
+
+:::caution Percent-Encoding in the script name
+
+The `[id].js` script must have the literal square brackets in the name. If your
+browser saved the file to `%5Bid%5D.js`. rename the file.
+
+:::
+
+On Linux or macOS or WSL:
+
+```bash
+cd pages
+curl -LO https://docs.sheetjs.com/next/index.js
+curl -LO https://docs.sheetjs.com/next/getServerSideProps.js
+curl -LO https://docs.sheetjs.com/next/getStaticPaths.js
+curl -LO https://docs.sheetjs.com/next/getStaticProps.js
+cd sheets
+curl -LOg 'https://docs.sheetjs.com/next/[id].js'
+cd ../..
+```
+
+5) Test the deployment:
+
+```bash
+npx next
+```
+
+Open a web browser and access:
+
+- http://localhost:3000 landing page
+- http://localhost:3000/getStaticProps shows data from the first sheet
+- http://localhost:3000/getServerSideProps shows data from the first sheet
+- http://localhost:3000/getStaticPaths shows a list (3 sheets)
+
+The individual worksheets are available at
+
+- http://localhost:3000/sheets/0
+- http://localhost:3000/sheets/1
+- http://localhost:3000/sheets/2
+
+6) Stop the dev server and run a production build:
+
+```bash
+npx next build
+```
+
+The final output will show a list of the routes and types:
+
+```
+Route (pages) Size First Load JS
+┌ ○ / 551 B 81.7 kB
+├ ○ /404 194 B 77.2 kB
+├ λ /getServerSideProps 602 B 81.7 kB
+├ ● /getStaticPaths 2.7 kB 83.8 kB
+├ ● /getStaticProps 600 B 81.7 kB
+└ ● /sheets/[id] (312 ms) 580 B 81.7 kB
+ ├ /sheets/0
+ ├ /sheets/1
+ └ /sheets/2
+```
+
+As explained in the summary, the `/getStaticPaths` and `/getStaticProps` routes
+are completely static. 3 `/sheets/#` pages were generated, corresponding to 3
+worksheets in the file. `/getServerSideProps` is server-rendered.
+
+7) Try to build a static site:
+
+```bash
+npx next export
+```
+
+:::note The static export will fail!
+
+A static page cannot be generated at this point because `/getServerSideProps`
+is still server-rendered.
+
+:::
+
+8) Remove `pages/getServerSideProps.js` and rebuild with `npx next build`.
+
+Inspecting the output, there should be no lines with the `λ` symbol:
+
+```
+Route (pages) Size First Load JS
+┌ ○ / 551 B 81.7 kB
+├ ○ /404 194 B 77.2 kB
+├ ● /getStaticPaths 2.7 kB 83.8 kB
+├ ● /getStaticProps 600 B 81.7 kB
+└ ● /sheets/[id] (312 ms) 580 B 81.7 kB
+ ├ /sheets/0
+ ├ /sheets/1
+ └ /sheets/2
+```
+
+9) Generate the static site:
+
+```bash
+npx next export
+```
+
+The static site will be written to the `out` subdirectory, which can be hosted with
+
+```bash
+npx http-server out
+```
+
+The command will start a local webserver on port 8080.
+
+
+
## NuxtJS
`@nuxt/content` is a file-based CMS for Nuxt, enabling static-site generation
@@ -99,7 +403,7 @@ neatly with nested `v-for`:
### Nuxt Content Demo
-Complete Example (click to show)
+Complete Example (click to show)
:::note
diff --git a/docz/static/next/[id].js b/docz/static/next/[id].js
new file mode 100644
index 0000000..7ad71e9
--- /dev/null
+++ b/docz/static/next/[id].js
@@ -0,0 +1,47 @@
+import Head from 'next/head';
+import { readFile, set_fs, utils } from 'xlsx';
+import { join } from 'path';
+import { cwd } from 'process';
+
+export default function Index({type, html, name}) { return (
+
+
+
{`SheetJS Next.JS ${type} Demo`}
+
+
+
+ {`SheetJS Next.JS ${type} Demo`}
+ This demo reads from /sheetjs.xlsx
+ {name}
+
+
+
); }
+
+let cache = [];
+
+export async function getStaticProps(ctx) {
+ if(!cache || !cache.length) {
+ set_fs(await import("fs"));
+ const wb = readFile(join(cwd(), "sheetjs.xlsx"));
+ cache = wb.SheetNames.map((name) => ({ name, sheet: wb.Sheets[name] }));
+ }
+ const entry = cache[ctx.params.id];
+ return {
+ props: {
+ type: "getStaticPaths",
+ name: entry.name,
+ id: ctx.params.id.toString(),
+ html: entry.sheet ? utils.sheet_to_html(entry.sheet) : "",
+ },
+ }
+}
+
+export async function getStaticPaths() {
+ set_fs(await import("fs"));
+ const wb = readFile(join(cwd(), "sheetjs.xlsx"));
+ cache = wb.SheetNames.map((name) => ({ name, sheet: wb.Sheets[name] }));
+ return {
+ paths: wb.SheetNames.map((name, idx) => ({ params: { id: idx.toString() } })),
+ fallback: false,
+ };
+}
diff --git a/docz/static/next/getServerSideProps.js b/docz/static/next/getServerSideProps.js
new file mode 100644
index 0000000..139c752
--- /dev/null
+++ b/docz/static/next/getServerSideProps.js
@@ -0,0 +1,29 @@
+import Head from 'next/head';
+import { readFile, set_fs, utils } from 'xlsx';
+import { join } from 'path';
+import { cwd } from 'process';
+
+export default function Index({type, html}) { return (
+
+
+
{`SheetJS Next.JS ${type} Demo`}
+
+
+
+ {`SheetJS Next.JS ${type} Demo`}
+ This demo reads from /sheetjs.xlsx
+ It generates HTML from the first sheet.
+
+
+
); }
+
+export async function getServerSideProps() {
+ set_fs(await import("fs"));
+ const wb = readFile(join(cwd(), "sheetjs.xlsx"))
+ return {
+ props: {
+ type: "getServerSideProps",
+ html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]),
+ },
+ }
+}
diff --git a/docz/static/next/getStaticPaths.js b/docz/static/next/getStaticPaths.js
new file mode 100644
index 0000000..09affec
--- /dev/null
+++ b/docz/static/next/getStaticPaths.js
@@ -0,0 +1,34 @@
+import Head from 'next/head';
+import Link from "next/link";
+import { readFile, set_fs, utils } from 'xlsx';
+import { join } from 'path';
+import { cwd } from 'process';
+
+export default function Index({type, snames}) { return (
+
+
+
{`SheetJS Next.JS ${type} Demo`}
+
+
+
+ {`SheetJS Next.JS ${type} Demo`}
+ This demo reads from /sheetjs.xlsx
+ Each worksheet maps to a path:
+
+
+
); }
+
+export async function getStaticProps() {
+ set_fs(await import("fs"));
+ const wb = readFile(join(cwd(), "sheetjs.xlsx"))
+ return {
+ props: {
+ type: "getStaticPaths",
+ snames: wb.SheetNames,
+ },
+ }
+}
diff --git a/docz/static/next/getStaticProps.js b/docz/static/next/getStaticProps.js
new file mode 100644
index 0000000..280322b
--- /dev/null
+++ b/docz/static/next/getStaticProps.js
@@ -0,0 +1,29 @@
+import Head from 'next/head';
+import { readFile, set_fs, utils } from 'xlsx';
+import { join } from 'path';
+import { cwd } from 'process';
+
+export default function Index({type, html}) { return (
+
+
+
{`SheetJS Next.JS ${type} Demo`}
+
+
+
+ {`SheetJS Next.JS ${type} Demo`}
+ This demo reads from /sheetjs.xlsx
+ It generates HTML from the first sheet.
+
+
+
); }
+
+export async function getStaticProps() {
+ set_fs(await import("fs"));
+ const wb = readFile(join(cwd(), "sheetjs.xlsx"))
+ return {
+ props: {
+ type: "getStaticProps",
+ html: utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]),
+ },
+ }
+}
diff --git a/docz/static/next/index.js b/docz/static/next/index.js
new file mode 100644
index 0000000..ff0a830
--- /dev/null
+++ b/docz/static/next/index.js
@@ -0,0 +1,16 @@
+import Head from 'next/head';
+
+export default function Index() { return ( ); }
diff --git a/docz/static/next/sheetjs.xlsx b/docz/static/next/sheetjs.xlsx
new file mode 100644
index 0000000..beb3b2d
Binary files /dev/null and b/docz/static/next/sheetjs.xlsx differ