npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

workerful

v0.1.12

Published

A lightweight, worker driven, Electron alternative

Downloads

37

Readme

👷 workerful

A wonderful Electron standalone alternative 🌈, based on both system (Chrome/ium based) browser and node presence, hence weighting only 96.7KB to bootstrap.

// test it via NodeJS
npx workerful ~/project/folder/package.json

This project goal is to provide a minimalistic App Container fully based on system software and it uses by default ESM and all the modern Web Standards features through the (currently) most capable browser: Chrome/ium.

As the majority of Web developers and users most likely have NodeJS installed, and as pretty much everyone also has Chrome or Chromium installed on their machines, I've decided to give this approach a spin to hopefully see how much the community can create around its simple, yet extremely powerful, primitives that this tiny tool enables.


Quick Start

Given a project folder with this minimal structure:

project/
├▸ package.json
├▸ public/
│  ├▸ index.html
│  └▸ workerful.js
└▸ ...

and providing that package.json as optional argument, where the default one is retrieved out of the current working folder, this module will bootstrap, through the system NodeJS default version, an incognito instance out of any installed Chrome/ium system browser, confining all its data in the user's home directory under ~/.workerful/project-name.

package.json

The package.json file is used to describe all desired app bootstrap features through its optional workerful namespace, eventually created if not already present and updated once the application is closed.

{
  "type": "module",
  "workerful": {
    "name": "your project name",
    "ip": "localhost",
    "port": 0,
    "centered": true,
    "kiosk": false,
    "serializer": "json",
    "server": "",
    "browser": {
      "name": "chrome",
      "flags": []
    },
    "window": {
      "size": [400, 220],
      "position": [520, 340]
    }
  }
}
  • name is your app name. This will be used as top bar name in your OS and recognized with such name among your running processes
  • ip is your app IP v4 address. By default it's localhost but it can be any other IP address. This field can be overridden via environment WORKERFUL_IP variable.
  • port is your app port. By default the project runs on any available port and it's completely transparent for your app. This field can be overridden via environment WORKERFUL_PORT variable.
  • centered which can be true, to center the app on its first bootstrap, false to run the app on top-left corner and then run where it was left last time, or "always" to always start the app centered, even if the user moved the window elsewhere. This field can be overridden via environment WORKERFUL_CENTERED variable, where 1, y, yes, ok or always are valid values
  • kiosk to launch the app in kiosk mode (fullscreen). This field can be overridden via environment WORKERFUL_KIOSK variable, where 1, y, yes or ok are valid values
  • serializer is the stringify / parse used to post messages between the worker and either the main window thread or the server. By default it's "json" but it can be also "circular", based on flatted, or "structured", based on @ungap/structured-clone/json. As quick summary:
    • json is the default serializer. It's the preferred method for DB related data exchanges or simple payloads (and it's also slightly faster than others)
    • circular is like json but it allows circular references within passed data among "worlds"
    • structured allows both circular references and extra types such as Date, U/Int8Array, U/Int16Array, U/Int32Array or Float32Array, Error and more
  • server to optionally specify a request handler/listener for the app" where export default (req, res) => { res.writeHead(200); res.end() } would be a valid, bare-minimal, implementation. The file default export would be awaited and invoked with default NodeJS server references and if it does not return true on success, the server will respond with a 404. You can implement or orchestrate any logic you like through this handler but, if not specified, a default static file handler is used instead
  • browser is your app browser name based on open API. Currently only chrome is supported but in the future firefox and edge might be supported too. This field has two optional nested fields:
    • name which is currently only chrome
    • flags which allows extra flags to be passed on app bootstrap. See this curated list of Chrome/ium flags to know more and consider many flags are already in place.
  • window is your app UI size and position, reflected in the app via window.screenX and window.screenY for the position and window.screen.width plus window.screen.height for the size. This field has two optional nested fields, ignored when the app starts in kiosk mode:
    • size which is an array of [width, height] numbers
    • position which is an array of [x, y] numbers

public folder

This is the expected folder the server will automatically handle per each request and where all client side related files should be, most notably the index.html file and a workerful.js file to allow the automatically bootstrapped Worker to communicate or handle both the main window world and the server one.

workerful.js

The workerful.js file is automated after coincident/server and its minimal content would look like this:

import { server, window } from '/workerful'; // 🦄

const message = 'This is Workerful 🌈';

// show the message in the main window's body
window.document.body.append(message);

// log the message in console through the server
server.console.log(message);

These two primitives allow your worker code to send or receive data to show on the main thread UI or deal directly with anything available on the server, including importing modules or reaching out global references:

// import modules from the main thread
const { render, html } = await window.import('https://esm.run/uhtml');

// import modules from the server
const { default: os } = await server.import('os');

// or simply reach its globals
const { process } = server;

Due inevitable roundtrip delay between the worker and the main thread or the server one, it's important to keep in mind that highly / real-time reactive changes on the main UI are better passed along via listeners or exposed functionalities within the main thread, where it would receive, as example, only data to update or take care about, and so it goes for the server.

The rule of thumb here: delegate to respective domains heavy operations and expose utilities through dedicated modules which goal is to help the worker receive, or send, just data. This would be the TL;DR "best practice" of this worker driven pattern.


index.html

This file is the main file launched out of the box when the application starts and its minimal content would look like this:

<!doctype html>
<html>
  <head>
    <title>This is Workerful 🌈</title>
    <script type="module" src="/workerful"></script>
  </head>
  <body></body>
</html>

The /workerful import on both main window thread and the worker is automatically disambiguated through the logic.

On the main thread, it provides a minimal bootstrap logic that automatically bootstrap a Worker to drive the application but after that module, everything else is allowed just like any regular Web Application.

Both main /workerful and worker /workeful imports are handled on the NodeJS side and these two requests will never leak through the provided handler.

It is hence useless, or meaningless, to check for req.url and match against /workerful as that won't ever happen.