Board v2 · Firmware in developmentDraft
Web apps on the device
Single-file web apps stored on UPAN and served from the device itself — layout, manifest, security rules and how to install them.
UPAN can store your own control panels — simple web pages, written by you or by your AI agent — and serve them from the device at http://<device>/app/<name>/. A phone or PC in the same network opens the page directly from the device, and the page talks to the device's API on the same address. This works without internet and without installing anything on the phone. An app has exactly the rights of the logged-in session it runs in and nothing more; the motion MCU still checks every limit.
Note: This describes the planned design. The network module firmware that serves apps is not written yet, and details on this page may change.
Why apps live on the device
A page on the public website (https://…) cannot talk to a device at http:// in your local network:
- browsers block requests from an HTTPS page to plain HTTP addresses (mixed content);
- browsers increasingly restrict public pages from reaching local network addresses;
- a self-signed certificate on the device would be silently rejected by phones.
Serving the page and the API from the same origin — the device itself — removes all of these barriers and keeps working in a workshop without internet. This is why the public website does not control devices directly.
App layout
An app is a folder under /app/<name>/ with two files:
| File | Content |
|---|---|
index.html |
the whole app: HTML, CSS and JavaScript inline |
manifest.json |
name, title and icon for the app list on the built-in page |
{ "name": "feeder", "title": "Feeder", "icon": "↔" }
Rules for writing an app
These rules also apply when an AI agent writes the app for you:
- One self-contained
index.html. Everything inline. The only allowed script from outside the file is/lib/upan.js, served by the device. - No external URLs. No CDNs, fonts or analytics: a workshop may have no internet, and the device blocks them anyway (see below).
- Do not hard-code the device address. The app is loaded from the device, so the API is at
location.origin.upan.jsuses it automatically. - Log in through
upan.js. Web Crypto is not available on plain HTTP pages, andupan.jsbrings its own implementation. See Network API. - Take control before moving and expect other clients: see control ownership.
Content Security Policy
Every response under /app/ carries:
Content-Security-Policy: connect-src 'self'
An app can therefore connect only to the device it came from. It cannot send data from the device to a third-party server.
Rights
An app runs with the rights of the session it is logged into, like any other network client. There are no "trusted" apps. Changing machine limits is not possible from an app, because it needs USB and a button press on the device.
Example: a jog and feed panel
<!doctype html>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Panel</title>
<script src="/lib/upan.js"></script>
<style>
body{font:18px system-ui;margin:16px;display:grid;gap:12px}
button{font-size:24px;padding:20px}
#stop{background:#c00;color:#fff}
</style>
<div id="pos">—</div>
<button id="minus">◀ JOG</button>
<button id="plus">JOG ▶</button>
<button id="feed">Feed 150 mm</button>
<button id="stop">STOP</button>
<script>
(async () => {
const upan = await UPAN.connect();
upan.units = "mm";
await upan.acquireControl();
upan.onTelemetry(t => pos.textContent = t.position.toFixed(2) + " mm", { hz: 20 });
const hold = (btn, v) => {
btn.onpointerdown = () => upan.jog(v);
btn.onpointerup = btn.onpointerleave = () => upan.jog(0);
};
hold(minus, -20); hold(plus, 20);
feed.onclick = () => upan.moveRel(150).catch(e => alert(e.message));
stop.onclick = () => upan.stop();
})();
</script>
The upan.js calls in this example follow the planned API, which is not final yet. See upan.js.
Installing an app
Planned ways to put an app on the device; all need a logged-in session, none needs control of the axis:
| Way | How |
|---|---|
| Built-in page | drag and drop the file onto the device page at / |
| REST | PUT /api/v1/apps/<name>/<path>, DELETE /api/v1/apps/<name> to remove; list with GET /api/v1/apps |
upan-mcp |
an install command for agents; the exact name is not final yet |
Storage
Apps are kept in a file system partition in the network module's 4 MB flash, next to its two firmware update slots. The target is about 1 MB for all apps — enough for dozens of single-file panels. The exact size and the number of apps are not final yet.
Installing presets by code
Note: Planned, not final.
Presets on the website (programs, apps and settings for a task) cannot be pushed from the website to your device, for the reasons above. The direction that works is the other way round: the device fetches. The proposed flow:
- The preset page on the website shows a short code.
- You enter the code on the device's built-in page; the device downloads the preset from the website. This needs internet access for the device or the phone.
- Without internet: download the preset as a file and drag it onto the built-in page.
- For agents: an install command in
upan-mcp.
A preset cannot bypass machine limits: the motion MCU checks everything it runs, whoever wrote it.