How Factorial works
Factorial runs the process-improve Python package inside your browser tab. The server sends the app's files and nothing more: your factors, results and analyses stay on your machine.
What runs where
Your browser tab
- The page (
index.htmland its JavaScript modules) draws the form, the run sheet, the tables and the charts, and holds the study you are working on. - A Web Worker runs Python. Pyodide is CPython compiled to
WebAssembly; in a worker, a long computation leaves the page free to scroll and type in. The page sends it
each request as JSON, and
web/bootstrap.pyanswers with the same process-improve functions you would call in Python:generate_design,compare_designs,TrueProcessandanalyze_experiment. - The charts are process-improve's own Plotly figures, drawn in the page with Plotly.js.
- Your studies are saved in this browser's IndexedDB as you work, the 30 most recent, and a brief not yet made into a run sheet is kept in its local storage. Clearing this site's data in the browser deletes them.
- A link to a study holds the study itself, compressed, after the
#. A browser does not send that part of an address to any server: the link travels only where you paste it. - The workbook and the notebook (
.xlsxand.ipynb) are written in the tab and saved by your browser, as any download is.
What reaches a server
- factori.al sends the app's files. It has no database, no accounts, no cookies and no
tracking script. Its web server writes one line per request, as web servers do: the time, the file asked for,
the result, the browser's name (its
User-Agent) and the page that linked here. Your address is cut to its network before the line is written (the first 24 bits of an IPv4 address, the first 48 of an IPv6 one), and the lines are kept for 90 days, to count visits. - jsDelivr and PyPI send Python and its packages, the first time and after a new version; your browser keeps them. They see an ordinary download, as for any web page that uses them, and nothing of your study.
What this copy is built with
These are the versions this copy of Factorial loads, read from the files it loads them by:
runtime.json and wheels/manifest.json.
| process-improve | the wheel built with this copy |
|---|---|
| Python, in WebAssembly | Pyodide |
| From the Pyodide release | numpy, pandas, scipy, statsmodels and more |
| From PyPI | openpyxl and plotly |
| Charts | Plotly.js |
Read the code
All of it is open source, under the MIT license, at github.com/kgdunn/process-improve. To check what it does with your data, these are the places to read:
web/: the page, andworker.js, which starts Python;web/bootstrap.py: every call the page makes into Python;scripts/build_web_app.py: how this site is built from the repository;deploy/factorial/: the server at factori.al, its configuration and what it logs;tests/web/: the tests that check the page, in a real browser and under Pyodide, on every change.
Run it yourself
Factorial is a folder of plain files, so it runs on any web server. To build that folder from the code and serve it on your own machine (with uv installed):
git clone https://github.com/kgdunn/process-improve
cd process-improve
uv sync --all-extras
uv run python scripts/build_web_app.py --out site --serve
then open http://localhost:8000. The site folder can be copied to any web server:
nginx, Apache, Caddy, an internal server or GitHub Pages. It has to be served over HTTP, as Python's files are
fetched by the worker, so opening index.html from a disk does not work.
deploy/factorial/
holds the setup that serves factori.al, with deploys and roll-backs, as a worked example.
On a network without access to the internet, the browser has to fetch Pyodide, the two PyPI packages and
Plotly.js from inside it as well: copy them to a server there, and change their addresses in
web/worker.js (Pyodide and the PyPI packages) and web/charts.js (Plotly.js).