---
title: Lume
pagination_prev: demos/net/index
pagination_next: demos/mobile/index
sidebar_custom_props:
type: native
---
Lume is a lightweight, fast and flexible static site generator.
The official [Sheets plugin](https://lume.land/plugins/sheets/) uses SheetJS to
load data from spreadsheets. New users should consult the official docs.
Lume supports refreshing data during development. The generated static sites
include the raw data without referencing the underlying spreadsheet files.
## Integration Details
### Installation
The `sheets` plugin can be imported and invoked in `_config.ts`:
```ts title="_config.ts"
import lume from "lume/mod.ts";
// highlight-next-line
import sheets from "lume/plugins/sheets.ts";
const site = lume();
// highlight-next-line
site.use(sheets());
export default site;
```
### Usage
:::note
The official documentation includes notes for more advanced use cases.
:::
Spreadsheet files added in the `_data` subdirectory are accessible from template
files using the name stem.
For example, [`pres.numbers`](https://sheetjs.com/pres.numbers) can be accessed
using the variable `pres` in a template.
#### Single-Sheet Workbooks
When a workbook has one worksheet, the data is an array of row objects:
```liquid title="single.njk"
Name | Index |
{% for row in pres %}
{{ row.Name }} |
{{ row.Index }} |
{% endfor %}
```
#### Multi-Sheet Workbooks
_Reading the First Worksheet_
The `sheets` plugin accepts an options argument. If the `sheets` property is
set to `"first"`, then the plugin will expose row objects for the first sheet:
```ts title="_config.ts"
// the first sheet of each file will be parsed and converted to row objects
site.use(sheets({ sheets: "first" }));
```
_Reading all Worksheets_
The default behavior, when workbooks have multiple sheets, is to present objects
whose keys are worksheet names and whose values are arrays of row objects.
For example, if `pres.numbers` had a sheet named `"Presidents"` and another
sheet named `"VicePresidents"`, then the following snippet would print data
from the `"Presidents"` sheet:
```liquid title="multi.njk"
Name | Index |
{% for row in pres["Presidents"] %}
{{ row.Name }} |
{{ row.Index }} |
{% endfor %}
```
## Complete Example
:::note
This was tested against `lume v1.15.3` on 2023 March 14.
This example uses the Nunjucks template format. Lume plugins support additional
template formats, including Markdown and JSX.
:::
1) Create a stock site:
```bash
mkdir -p sheetjs-lume
cd sheetjs-lume
deno run -Ar https://deno.land/x/lume/init.ts
```
When prompted, enter the following options:
- `Choose the configuration file format`: select `_config.ts`
- `Do you want to install some plugins now?`: select `Yes`
- `Select the plugins to install`: scroll down, select `sheets`, and submit
The project will be configured and modules will be installed.
2) Download and place in a `_data` folder:
```bash
mkdir -p _data
curl -L -o _data/pres.numbers https://sheetjs.com/pres.numbers
```
3) Create a `index.njk` file that references the file. Since the file is
`pres.numbers`, the parameter name is `pres`:
```liquid title="index.njk"
Presidents
Name | Index |
{% for row in pres %}
{{ row.Name }} |
{{ row.Index }} |
{% endfor %}
```
4) Run the development server:
```bash
deno task lume --serve
```
To verify it works, access http://localhost:3000 from your web browser.
Adding a new row and saving `pres.numbers` should refresh the data
5) Stop the server (press `CTRL+C` in the terminal window) and run
```bash
deno task lume
```
This will create a static site in the `_site` folder, which can be served with:
```bash
npx http-server _site
```
Accessing the page http://localhost:8080 will show the page contents.
This site is self-contained and ready for deployment!