Make documentation standalone and generalize examples

This commit is contained in:
Melvin Strobl
2026-10-25 14:43:20 +01:00
parent 13bf0f76d7
commit bdb18b99da
57 changed files with 553 additions and 481 deletions
+5 -5
View File
@@ -26,11 +26,11 @@ invalidates its access. MCP uses a separate signing key at
`OAUTH_PRIVATE_KEY_FILE`; rotating that key invalidates all MCP tokens.
An instance connected to a [portal](../interface/portal.md) also answers
through it, at `https://hub.fluksio.com/i/<instance-id>/mcp` (the portal's
own `hub.` host for a custom one). The portal forwards the endpoint and its
OAuth, and the instance checks the agent's token as it does locally. The
consent page opens in the instance as the portal serves it, so open the
instance from the portal first if this browser has not recently.
through the portal's API address, for example
`https://portal.example.com/i/<instance-id>/mcp`. The portal forwards MCP and
OAuth requests; the instance checks the agent's token as it does locally.
Open the instance from the portal first so the browser can show its consent
page.
## Available tools
+2 -2
View File
@@ -57,7 +57,7 @@ that instance's running engine; plain mode refuses to start a duplicate.
| `--admin-email ADDR` | `admin@example.com` | First admin account |
| `--admin-password PW` | Generated | First admin password |
| `--enroll CODE` | Unset | Enroll before starting, if not already paired |
| `--portal URL` | `https://hub.fluksio.com` | Portal used by `--enroll` |
| `--portal URL` | Built-in portal address | Portal used by `--enroll` |
| `--max-runs N` | `4` | Concurrent batch runs |
| `--max-cascades N` | `4` | Concurrent live cascades |
| `--max-workers N` | `4` | Local Python worker processes |
@@ -106,7 +106,7 @@ from the instance's project directory, or select it explicitly.
| Option | Purpose |
|---|---|
| `--portal URL` | Use another portal instead of `https://hub.fluksio.com` |
| `--portal URL` | Use another compatible portal |
| `--as EMAIL` | Choose the local superuser represented by portal sessions |
| `--data-dir PATH` | Select instance storage |
| `--global` | Select `~/.fluksio` |
+7 -17
View File
@@ -132,9 +132,9 @@ storage; emitted frames alone are not recorded as run artifacts.
### Making clips playable on an LVGL panel
A wall panel that renders dashboards natively, such as an ESP32-P4 running
openpanel, decodes only H.264 Constrained Baseline (in software, about 29 fps
at 640×360) and MJPEG. It refuses clips straight from a phone or camera, which
are usually Main or High profile at 1080p or more. Re-encode those with a node
openpanel, decodes H.264 Constrained Baseline and MJPEG. Clips straight from
a phone or camera may use an unsupported profile or resolution, such as
Main or High profile at 1080p or more. Re-encode those with a node
that takes a `video` input port `clip` and has a `video` output port
`panel_clip`:
@@ -288,19 +288,9 @@ downloads them again. Point `MODELS` at a directory under `/data` to keep them
on the volume. An [attached worker](workers.md) starts a process per call and
loads the model each time.
What it costs, measured on a 2016 server CPU (Xeon E5-2683 v4):
| | Size | Memory | 3 s of speech, one core | All cores |
|---|---|---|---|---|
| Packages | 150 MB download, 460 MB installed | | | |
| Whisper `tiny` | 78 MB | 300 MB | 1.6 s | 0.7 s |
| Whisper `base` | 148 MB | 375 MB | 2.9 s | 1.2 s |
| piper `en_US-lessac-medium` | 63 MB | 250 MB | 0.6 s | 0.3 s |
Each model downloads once, on its node's first call. Loading it takes about a
second for Whisper and four seconds for piper. Memory is the worker's peak while
it holds the model. These figures come from piper's own speech fed back into
Whisper. A room microphone is harder, on `tiny` most of all.
Models download on first use. Speed, memory use and recognition quality depend
on your hardware, model and audio. Try a short clip from your own microphone
before choosing a model; `tiny` is a useful first stop on a small CPU.
## Printing
@@ -391,7 +381,7 @@ access token; see [The HTTP API](api.md).
managed environment can also install your project from a Modules manifest:
```text
-e /home/you/my-research
-e /path/to/my-research
numpy>=2
```
+7 -6
View File
@@ -38,11 +38,12 @@ export FLUKSIO_WORKER_TOKEN='<token from the engine>'
fluksio-worker \
--url wss://fluksio.example.com/api/v1/workers/attach \
--labels gpu,cuda12 \
--python /opt/torch-venv/bin/python
--python /path/to/node-venv/bin/python
```
Use your engine's hostname. `--python` selects the environment containing the
node's dependencies, such as PyTorch or a device SDK. If you install the worker
Replace the address and interpreter path with your own. `--python` selects
the environment containing the node's dependencies, such as PyTorch or a
device SDK. If you install the worker
in that environment, you can omit the option. An engine installation also
provides the same agent as `fluksio worker`.
@@ -55,7 +56,7 @@ provides the same agent as `fluksio worker`.
| `--python` | worker's interpreter | Python used for node code |
| `--parallel` | `1` | concurrent calls |
| `--artifact-url` | derived from `--url` | artifact endpoint, if hosted separately |
| `--service-host` | address the engine sees | host in a service's url, when the engine reaches this machine elsewhere, such as through a tunnel |
| `--service-host` | address the engine sees | reachable hostname or IP for services, when the connection address is unsuitable |
| `--cpus` | detected | advertised CPU count |
| `--gpus` | detected | advertised GPU count; explicit `0` means none |
| `--ram-mb` | detected | advertised memory in MB |
@@ -183,7 +184,7 @@ in `$DATA_DIR/provisioners.json`, replacing the example addresses and paths:
[{
"type": "slurm",
"name": "hpc",
"login": "me@login.cluster",
"login": "user@login.cluster.example.com",
"ssh_key": "/secrets/hpc_ed25519",
"engine_url": "wss://fluksio.example.com/api/v1/workers/attach",
"max_idle_s": 300,
@@ -195,7 +196,7 @@ in `$DATA_DIR/provisioners.json`, replacing the example addresses and paths:
"ram_mb": 65536,
"labels": ["gpu"],
"sbatch": ["--partition=gpu", "--gres=gpu:1", "--time=04:00:00"],
"prerun": ["module load cuda/12", "source ~/venvs/fluksio/bin/activate"]
"prerun": ["module load cuda", "source /path/to/node-venv/bin/activate"]
}]
}]
```
+12 -10
View File
@@ -7,10 +7,11 @@ No hardware required for the first lap.
You need Git and Docker with Compose v2 on a 64-bit machine, x86 or ARM. A
Raspberry Pi 4 or 5 with a 64-bit OS works too. Clone the app repository and
start its single container:
start its single container. Replace `<repository-url>` with the app
repository's URL:
```sh
git clone https://git.stroblme.de/Fluksio/app.git fluksio
git clone <repository-url> fluksio
cd fluksio
docker compose up -d
docker compose logs fluksio
@@ -115,24 +116,25 @@ See [Dashboards and devices](../interface/dashboards.md) for widgets and pairing
a wall tablet.
For longer-term history, add an **InfluxDB** node that consumes
`living_temperature`. It needs the `influx` extra. Configure your server URL, organization, bucket, token
and `writes` mapping. Store the token under **Secrets** and select it in the
node's credential field. [Node types](../reference/node-types.md#influxdb)
`living_temperature`. It needs the `influx` extra. Configure your database URL,
organization, bucket, token and `writes` mapping. Store the token under
**Secrets** and select it in the node's credential field.
[Node types](../reference/node-types.md#influxdb)
has the write and query formats.
Fluksio does not run an InfluxDB server either. Use your own.
Run InfluxDB separately, just like the MQTT broker.
## Run it long term
The container from `compose.yml` is fit for long-term use. It restarts with
Docker, and `/data` holds everything it keeps: the database, the flows,
secrets, artifacts and its Redis. Back up that volume. Compose names it
`fluksio_data`.
secrets, artifacts and its Redis. Back up that volume. Compose prefixes its
name with your project name.
The container speaks plain HTTP. For access from outside your network, put a
reverse proxy with HTTPS and WebSocket support in front of it, such as Caddy,
Traefik or nginx, or [enroll with the portal](../interface/portal.md). A
Caddyfile for `fluksio.example.com` is one line:
Traefik or nginx, or [enroll with the portal](../interface/portal.md).
For example, a Caddyfile can proxy your app address:
```text
fluksio.example.com {
+2 -3
View File
@@ -1,8 +1,7 @@
# Pick your starting point
Choose the setup that fits your work.
Both paths lead to the same Fluksio engine, with a first flow to try along the way.
This is really just about a decision what you're planning to do with Fluksio.
Pick the setup that fits your work. Both paths lead to the same engine, with
a first flow to try along the way.
<div class="fluksio-lanes" markdown>
+10 -10
View File
@@ -501,13 +501,13 @@ start and renames the file `panels.json.migrated`.
### A screen without a browser
The openpanel firmware, kept in its own repository, draws dashboards as native
widgets on an ESP32-P4 wall panel (Waveshare ESP32-P4-WIFI6-Touch-LCD-7B,
1024×600). Once its config page points it at this instance (the device's link
works too, the device keeps only its address), it shows the pairing code itself; enter it as in step 5. It reads the same published
dashboards and live values and draws every widget type with two exceptions,
both shown as a placeholder: a website tile that embeds a page (image tiles
work), and a chart of runs, which a device credential may not read. Media tiles
Compatible device firmware can draw dashboards as native widgets without a
browser. For example, openpanel supports ESP32-P4 wall panels. Once its
config page points it at this instance, it shows a pairing code; enter it as
in step 5. The device's link works too, since the device keeps only the
instance address. It reads the same published dashboards and live values.
Embedded website tiles and run charts show placeholders; image tiles work,
and device credentials cannot read runs. Media tiles
play MJPEG streams, pushed frames, images, and H.264 Baseline or MJPEG clips up
to 640×360. Re-encode other clips with the [clip recipe](../code/nodes.md#making-clips-playable-on-an-lvgl-panel).
@@ -625,9 +625,9 @@ A camera device (openpanel on a NANO) reports these ports:
dashboard tile, the preview on the device's page, a screen through the
portal), or a node of a running flow reads its message. Once its flow wires
`camera`, the device's page shows a **Camera** preview. A flow that reads
`camera` keeps it sending all the time, about 300 GB a month through a cloud
instance, so the Device node warns when a node in its flow reads a port that
sends on demand. Have flows read `snapshot` or `person` instead. To keep the
`camera` keeps it sending continuously. Traffic depends on resolution, frame
rate and image quality, so the Device node warns when a flow node reads an
on-demand port. For occasional updates, read `snapshot` or `person`. To keep the
picture of whoever came by, a node reading `snapshot` can hand it on to a
message of its own, which a media tile shows until the next one:
+4 -3
View File
@@ -1,9 +1,10 @@
# The dashboard app
Open your instance's app address, or select it at [fluksio.com](https://fluksio.com)
after enrollment. For the local Docker setup, use
[app.localhost](http://app.localhost) and the admin login printed by
`make init`. See [Getting started](../getting-started/index.md) for setup.
after enrollment. For the single-container setup, open
[localhost:8080](http://localhost:8080) and use the admin login printed by
`docker compose logs fluksio`. See [Getting started](../getting-started/index.md)
for setup.
## Finding your way around
+5 -4
View File
@@ -18,7 +18,7 @@ API requests, responses and live updates through the connection.
fluksio enroll <code>
```
The CLI uses `https://hub.fluksio.com` by default. If you started the engine
The CLI uses the built-in portal address by default. If you started the engine
with `--data-dir` or `--global`, use the same option when enrolling. A running
engine picks up the connection automatically; otherwise start it with
`fluksio serve`.
@@ -65,12 +65,13 @@ removing them at the portal, or disconnecting, deletes them.
## Hooks and agents through the portal
The portal also forwards a flow's hooks and the MCP endpoint, so they work
without an inbound port:
without an inbound port. Replace `portal.example.com` with your portal's API
address in these examples:
- A webhook or a served WebSocket:
`https://hub.fluksio.com/i/<instance-id>/hooks/<flow>/<url>/<secret>`,
`https://portal.example.com/i/<instance-id>/hooks/<flow>/<url>/<secret>`,
with `wss://` for a socket.
- An agent: `https://hub.fluksio.com/i/<instance-id>/mcp`, see
- An agent: `https://portal.example.com/i/<instance-id>/mcp`, see
[Agents over MCP](../code/agents.md).
Through the portal a hook needs a [secret](../reference/node-types.md#http).
+2 -2
View File
@@ -105,8 +105,8 @@ comma separated. Empty, the default, is the minimal engine.
| `server` | all of the above |
A node whose extra is missing says so on the canvas. The same names work as
pip extras, such as `pip install 'fluksio[mqtt]'`. Connector packages built
with `make connectors` are installed into the image too.
pip extras, such as `pip install 'fluksio[mqtt]'`. To include connectors, place
their wheels in `backend/connector-wheels/` before building the image.
## Environment
+1 -1
View File
@@ -377,7 +377,7 @@ name of its own, in the node panel's port name field or as
| `model` | empty | the trained model, an artifact digest; empty runs wren's demo model |
| `min_confidence` | empty | the confidence a call needs; empty takes the model's own threshold |
| `targets` | empty | by target port, what the model is told of it and how far it is trusted (below) |
| `aliases` | empty | your own words, or words the recogniser hears wrong, in the model's: `{"traverse": "living room light", "page too": "patio"}` |
| `aliases` | empty | map your own names to the model's target names, such as `{"desk lamp": "office light"}` |
| `examples` | empty | for training only, commands to learn beyond the ones wren generates (below) |
| `tests` | empty | for training only, commands a new model is scored on (below) |
+1 -1
View File
@@ -3,7 +3,7 @@
* Follows the zensical custom color scheme approach
* (https://zensical.org/docs/setup/colors/#custom-color-schemes): override the
* Material `--md-*` CSS variables per [data-md-color-scheme]. Colors mirror the
* design tokens in ../DESIGN.md → ../../DESIGN-GUIDELINES.md: neutral white /
* design tokens in DESIGN-GUIDELINES.md at the repository root: neutral white /
* near-black surfaces carrying one slate-blue accent, with terracotta reserved
* for the single secondary affordance per view. The built-in `default` (light)
* and `slate` (dark) schemes stay as the base so all of Material's derived