Community registry of electerm widgets: a pure static site on Cloudflare Workers Static Assets. No Worker script, no database, no login, no admin, and no write API.
This site only indexes metadata. Widget code is downloaded from each
author's repository at a pinned commit. Installing a widget means trusting its
author — a widget's main.js runs inside the electerm main process with full
Node.js privileges.
Widgets that merely repackage an electerm built-in are not listed here; the registry is for functionality that is not already in the app.
npm install # generates package-lock.json; commit it
npm test
npm run lint
npm run build # fetches sources; renders pug/stylus; writes public/
npm run wdev # wrangler dev on localhost:26790
public/ is generated and git-ignored; it is rebuilt by npm run build on
every deploy. No database or migration step is needed.
The site is built from src/, mirroring electerm.org:
src/views/— pug pages (index.pug,widgets.pug,widget.pug,404.pug) plus sharedparts/src/css/—main.stylrequires one file per section fromcss/parts/src/js/pages/— one native ESM entry per page, importingjs/parts/
/widgets/ (public/widgets/index.html) is the standalone index: it lists every
widget and nothing else — no hero, how-to or trust sections. It shares the site
header/footer and the copy-install button, and loads only header.js + copy.js.
Shared brand assets (favicons, the electerm.png wordmark, PWA icons) are
referenced directly from https://electerm.org rather than copied here —
that origin already serves them with Access-Control-Allow-Origin: *. The
build generates only the site-specific public/site.webmanifest, whose icon
URLs are absolute.
npm run build compiles the stylus parts into a content-hashed
styles.<hash>.css, renders every pug page, and copies js/
into public/. Browser scripts are plain ESM, so there is no bundler.
GET /api/v1/index.json, GET /api/v1/widgets/<id>.json,
GET /api/v1/revocations.json and GET /health are plain static files
generated from data/widgets.json. generatedAt is the build time, not the
request time. public/_headers adds Access-Control-Allow-Origin: * and
Cache-Control: public, max-age=300 to /api/v1/*; unmatched paths return
404.html via not_found_handling = "404-page".
Only <id>.json URLs exist — the registry filesUrl always uses that form.
Open a PR that appends an entry to data/widgets.json:
{
"host": "github.com",
"owner": "electerm",
"repo": "electerm-widget-tftp",
"subdir": "",
"ref": "<40-char lowercase hex commit sha>"
}ref must be a full 40-character lowercase hex commit sha (not a tag or
branch); pinning a sha is what makes the digest reproducible. The widget's
package.json must contain an electerm object whose id matches
^[a-z0-9-]+$.
.github/workflows/deploy.yml runs on push to main, daily, and on dispatch.
It needs these repository secrets:
CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_IDGITHUB_TOKENis provided automatically by Actions.
The workflow runs npm run build and then wrangler deploy. Commit the
package-lock.json produced by npm install so npm ci works in CI.
The site only indexes metadata; code is downloaded from the author's repo.
Installing a widget is equivalent to trusting its author — main.js runs in
the electerm main process with full Node.js privileges.