Custom widget with Pug, Python and Parcel.js

Real-life example

SQL widget implements a basic SQL selector widget thanks to the new SQL endpoint. The URL to use it as a custom widget is: ; the source is available here.

There is a sample page making use of it here.
You may try, for example:

select distinct
  from 'Values' v, 'Labels' l
  where v.Labels GLOB '*[^0-9]'||||'[^0-9]*'
  and l.Label in ('Third', 'kkk')

Install dependencies


  1. Install Python 3.9 (at the moment of writing, as it’s required by Transcrypt 3.9): cf. your system’s doc
  2. Create a folder for your project: mkdir my_widget && cd my_widget
  3. Within this folder, create a new Python venv: python3 -m venv py
  4. Activate this venv: source py/bin/activate
  5. Install Transcrypt: pip install transcrypt


(Assuming you’re still within your project’s folder with your venv activated.)

  1. Install Parcel.js: yarn add --dev parcel
  2. Create a .parcelrc file with this content:
  "extends": ["@parcel/config-default"],
  "transformers": {
    "*.py": ["parcel-transformer-transcrypt"]

Create your widget

Create those two files in your project’s directory. We’re taking the same onRecord example as Grist’s documentation.


Learn X in Y minutes gives the basics and references to documentation.

doctype html
    title onRecord
    pre#readout Waiting for data...
    script(type="module" src="")

We’re using document.querySelector instead of document.getElementById here: it shows that pug’s syntax makes it very easy to identify how to select elements.


  lambda record: document.querySelector('#readout').innerHTML = JSON.stringify(record, null, 2)

Launch Parcel.js

yarn parcel index.pug will automatically download required JavaScript packages, prepare files and serve them. It’s then possible to define a custom widget on Grist, using http://localhost:1234/ (by default) as URL. The widget will automatically reload every time the files are modified.

Once development is finished, yarn parcel build index.pug --public-url ./ will produce files suitable for production in the dist folder, that should be put online.

From then on, every time one works on the project, the only steps are activating the venv and launching Parcel:

source py/bin/activate
yarn parcel index.pug

Just tried it. Very cool!

Interesting, although I have no idea what an SQL Selector is and what it does :smiley:

It’s like a shorthand to mean “an SQL widget that can be used as a selector”. A custom widget can be used to select data in a linked table by using grist.ready({allowSelectBy: True}). In the sample, if your query returns an id column (like the example I give in the first post), the linked Values table on the right will show only corresponding entries.