--- title: Supercharge SvelteKit Apps with Spreadsheets sidebar_label: SvelteKit description: Make static websites from spreadsheets using SvelteKit. Seamlessly integrate data into your website using SheetJS. Rapidly develop web apps powered by data in Excel. pagination_prev: demos/net/index pagination_next: demos/mobile/index --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; [SvelteKit](https://kit.svelte.dev/) is a framework for generating static sites. It leverages modern technologies including ViteJS and SvelteJS[^1] [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing data from spreadsheets. This demo uses SvelteKit and SheetJS to pull data from a spreadsheet and display the content in an HTML table. We'll explore how to use a plugin to pull raw data from files and how to organize page scripts to process the files at compile time. The ["Complete Example"](#complete-example) section includes a complete website powered by an XLSX spreadsheet. :::info pass This demo focuses on server-side processing with SvelteKit and Svelte. The [Svelte demo](/docs/demos/frontend/svelte) covers general client-side usage. ::: The following diagram depicts the workbook waltz: ```mermaid flowchart LR file[(workbook\nfile)] subgraph SheetJS operations base64(base64\nstring) aoo(array of\nobjects) end html{{HTML\nTABLE}} file --> |vite.config.js\ndata loader| base64 base64 --> |+page.server.js\nload function| aoo aoo --> |+page.svelte\ncomponent| html ``` :::note This demo was tested on 2023 October 24 using SvelteKit `1.27.0` and Svelte `4.2.2` ::: ## Integration `+page.server.js` scripts can be pre-rendered by exporting `prerender` from the script. If the SheetJS operations are performed in the server script, only the results will be added to the generated pages! For static site generation, `@sveltejs/adapter-static` must be used. ### Loader SvelteKit projects use ViteJS under the hood. They expose the `vite.config.js` script. The "Base64 Loader" from the ViteJS demo[^2] can pull data from files into Base64 strings for processing in `+page.server.js` scripts. :::note pass The ViteJS demo used the query `?b64` to identify files. To play nice with SvelteKit, this demo matches the file extensions directly. ::: The loader should be added to `vite.config.js`. The code is nearly identical to the "Base64 Loader" ViteJS example. ```js title="vite.config.js" import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; import { readFileSync } from 'fs'; export default defineConfig({ assetsInclude: ['**/*.numbers', '**/*.xlsx'], plugins: [sveltekit(), { name: "sheet-base64", transform(code, id) { if(!id.match(/\.(numbers|xlsx)$/)) return; var data = readFileSync(id, "base64"); return `export default '${data}'`; } }] }); ``` #### Types For VSCodium integration, types can be specified in `src/app.d.ts`. The example data loader returns Base64 strings. Declarations should be added for each file extension supported in the loader: ```ts title="src/app.d.ts" declare global { declare module '*.numbers' { const data: string; export default data; } declare module '*.xlsx' { const data: string; export default data; } } ``` ### Data Processing For static sites, SheetJS operations should be run in `+page.server.js`[^3]. The script must include `export const prerender = true`[^4]. Assuming `pres.xlsx` is stored in the `data` directory from the project root, the relative import ```js import b64 from "../../data/pres.xlsx" ``` will return a Base64 string which can be parsed in the script. The workbook object can be post-processed using utility functions. The following example uses the SheetJS `read` method[^5] to parse spreadsheet files and the `sheet_to_json` method[^6] to generate arrays of row objects for each worksheet. The data presented to the page will be an object whose keys are worksheet names: ```js title="src/routes/+page.server.js" import b64 from "../../data/pres.xlsx"; import { read, utils } from "xlsx"; export const prerender = true; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const wb = read(b64); /** @type {[string, any[]][]} */ const data = wb.SheetNames.map(n => [n, utils.sheet_to_json(wb.Sheets[n])]); return Object.fromEntries(data); } ``` ### Data Rendering The shape of the data is determined by the loader. The example loader returns an object whose keys are worksheet names and whose values are arrays of objects. Using standard Svelte patterns, HTML tables can be generated from the data: ```html title="src/routes/+page.svelte"
Name | Index | {#each pres as p}
---|---|
{p.Name} | {p.Index} |