Home

Awesome

grist-static: Grist on static sites without embeds

This is a way to view and interact with .grist files (Grist spreadsheets) on regular websites, with no special back-end support needed. The idea here is that it would be great for making reports if we could put spreadsheets on a website like we do PDFs, with nice formatting and navigation options and not much fuss.

If you can run a special back-end, grist-core is the most battle-tested way to host Grist spreadsheets. And for many purposes Grist embedding may be adequate, where your embed a Grist spreadsheet from an external Grist installation (such as the hosted service offered by Grist Labs). But if you cannot host your data externally, and don't want the operational burden of standing up a Grist installation of your own, grist-static gives you a way to easily render Grist spreadsheets on regular websites. Like a PDF, people will be able to view the spreadsheet, navigate around in it, and search within it. Better than a PDF, they'll be able to change selections, and experiment with changing numbers to see what happens. Every viewer has their own copy, and their changes won't be seen by others, or stored. This would also be a scalable way to show a Grist document to millions of simultaneous users.

See an example

https://gristlabs.github.io/grist-static shows a couple of example Grist documents hosted on GitHub Pages:

https://user-images.githubusercontent.com/118367/227564527-82a9929c-40d3-4167-999f-6aeee4955723.mp4

Serving a Grist document on a static website

These days, PDFs can be placed on a website, and you can link to them with the expectation that browsers will show them nicely. Browsers don't have native support for Grist [yet :-)] but you can make a little wrapper page like this:

<!doctype html>
<html>
  <head>
    <meta charset="utf8">
    <script src="https://grist-static.com/latest.js"></script>
  </head>
  <body>
    <script>
      bootstrapGrist({
        initialFile: 'investment-research.grist',
        name: 'Investment Research',
      });
    </script>
  </body>
</html>

Grist CSV Viewer

Grist can handle data in multiple formats, including CSV. Since CSV is such a common format, and interacting with it online remains a chore, we've packaged grist-static into a streamlined csv-viewer.js utility specifically for viewing, sorting, filtering, any copy/pasting from CSV, directly in a webpage.

Just add the viewer in the head area of a webpage:

<head>
  <script src="https://grist-static.com/csv-viewer.js"></script>
</head>

Then you can make a button to open CSV from a URL:

<button data-grist-csv-open="transactions.csv">View CSV</button>

The CSV could be a file, or a URL of CSV data that your site generates for a user dynamically.

If you are working with links rather than buttons, the same approach works:

<a data-grist-csv-open="transactions.csv" href="#">View CSV</a>

You can of course style the buttons and links as you wish.

Grist CSV Viewer as a web component

The CSV Viewer can also be used as a web component called csv-viewer:

<html>
  <head>
    <script src="https://grist-static.com/csv-viewer.js"></script>
  </head>
  <body>
    <csv-viewer initial-data="path/to/data.csv" style="height: 500px; border: 1px solid green">
    </csv-viewer>
  </body>
</html>

The component in fact accepts the same set of options as the bootstrapGrist function, so you can configure it to show either a CSV file or (despite its name) a Grist document of your choice. Full list of options available:

More viewer options

We've seen that with csv-viewer.js, any element can be converted to a link that opens a popup with a CSV file. All you need to do is to add data-grist-csv-open attribute to it.

There are other options available.

There are also some predefined button classes, specifically grist and grist-large, that offer Grist's default styling.

For finer control, there is a global previewInGrist function with the same API as bootstrapGrist, but instead of rendering inline it opens a preview in a popup. This might be useful for any dynamically created content or files that are not available at the time of page load.

Differences with regular Grist

Tips for small .grist files

Grist spreadsheets by default store a lot of history in the .grist file. You can prune that history by building grist-core and then, in the grist-core directory, doing:

yarn run cli history prune PATH/TO/YOUR/doc.grist

Sorry this is awkward.

Building from source

git submodule update --init
make requirements
make build
make serve
# now visit http://localhost:3030/page/

The sequence above places a lot of links in the page directory, for convenience during development. To collect files for uploading, use instead:

make package
# everything you need is in dist/

Serving all files from your own website or CDN

All HTML examples so far have used https://grist-static.com/, a domain operated by Grist Labs that only serves static files. This domain logs traffic to measure usage, but does not set or track cookies. You can copy all needed files to your own website or CDN to keep your traffic completely private.

You can get the files needed by:

Tarballs (.tgz files) are a common archive format, with many free tools available for unpacking them. However you get there, in the end you will have a dist/ directory containing csv-viewer.js, latest.js, and many other files that make up Grist. Place that material where you wish, and update your URLs appropriately.

The jsdelivr CDN automatically mirrors packages placed on NPM, so let's use it as an example. We could replace:

<script src="https://grist-static.com/csv-viewer.js"></script>

with:

<script src="https://cdn.jsdelivr.net/npm/grist-static@latest/dist/csv-viewer.js"></script>

Of course, this particular change would simply move usage information to jsdelivr.net rather than grist-static.com, but you get the idea. Just use the same pattern for wherever you choose to place the files.

Roadmap

It could be neat to make user changes persist in their browser - OPFS may be a good option for that, once it has broad browser support. Other steps: