The application
A folder in your git repository: app/index.html, its assets, and an optional manifest.json declaring datasets and settings.
ArdaForm is four pieces that only make sense together: an application folder in your own git repository, a runtime that runs it on the device, the portal you manage everything from, and the device images that put the runtime on hardware. This page walks the whole loop — from a commit on your laptop to a screen on a counter three hundred miles away, and back.
Each part is useful on its own. Together they close the gap between "the demo works on my desk" and "two hundred of them work in customer sites".
A folder in your git repository: app/index.html, its assets, and an optional manifest.json declaring datasets and settings.
ArdaPlayer — one static Go binary that draws your page straight on the display hardware and hands it window.Arda.
Where you manage it all from a browser: projects, branches, devices, data, files, settings, the device screen. Behind it, ArdaForm's servers (the control plane), which every device keeps in touch with.
A Raspberry Pi image, a PC image and a USB installer stick from the portal's Downloads. Flash, boot, adopt. No Linux administration.
You push to GitHub; the devices take it from there. Nothing needs opening on the customer's network: each device keeps its own secure connection out to ArdaForm, and checks every instruction that comes down it — a signed message — before it acts.
The ArdaForm GitHub App reads the branch you connected to a project. Push, and ArdaForm hears about it.
The commit's app folder becomes one encrypted file (AES-256-GCM). Nothing from the repository is ever run.
Addressed to one device, carrying the file's fingerprint (SHA-256) and the key that opens it. It waits until the device is there to take it.
The device downloads it, checks the fingerprint, opens it in memory, gets it ready — and your app picks the moment to switch.
ArdaForm packs files; it never runs them. No npm install, no scripts, nothing executed from a customer's repository on our infrastructure. Symlinks, dotfiles and .env files are refused at the door.
A project has branches; each branch is fed by one connection to one git ref. A device follows one branch, so "what is on the device" always has exactly one answer.
An update arrives staged. The page is asked; five seconds of silence and it applies. An app mid-transaction can pause it, up to five times. A branch can also be set to a time window, or to apply only when the app says so.
Shop Wi-Fi drops. A router reboots. Somebody unplugs the wrong thing. A device that stops working because a DNS lookup failed is not a product — it's an incident.
So ArdaForm assumes the network will drop. Your app reads its data — a price list, a member list, today's bookings — from a copy kept on the device (a dataset), and saves what happens — a sale, a check-in — into a queue on the disk (the outbox) that survives a power cut and sends itself when the connection is back. Pictures and documents (files) are synced the same way and served from /storage/. The copy on the device always catches up with the portal's.
Under the hood: datasets are sealed on the device's disk; the outbox delivers at least once and is acknowledged by sequence number; files are content-addressed and hash-checked; nothing on the device is ever authoritative.
// Server truth, already on the disk, sealed
const catalogue = await Arda.db.dataset('catalogue')
// Re-read when a sync lands
Arda.on('sync', (name) => {
if (name === 'catalogue') render()
})
// Durable — queued locally, delivered later if the line is down
const { seq } = await Arda.db.push('sales', {
till: Arda.config.till_no ?? 1,
items, total,
})
// A picture the file plane has synced
img.src = '/storage/catalogue/' + item.image
Support is where device businesses lose money. Everything below exists so that "it's frozen again" can be answered without a two-hour drive — from the device's screen in the portal.
Online or offline, from the device's own regular check-in (its heartbeat). A device that reboots or shuts down on purpose says goodbye first, so the portal shows it offline at once instead of after a missed check-in.
Hostname, board, OS, player version, local IP, the screens attached and what model each panel is, inputs, audio, printers and serial adapters — refreshed as things change.
Switch it on and the app's own console.* lines stream in — including the last few hundred lines from before you asked. It switches itself off again.
A picture of the screen, on demand or every few seconds; the live console; one expression evaluated in the page; the page source — and a lossless, full-resolution screenshot of every connected screen, with a download button.
Brightness, contrast and volume sliders that move the real screen as you drag, and a scale per screen; reboot, shut down, apply a waiting update, approve a device an install code held back, issue a new device password — and Remove, which wipes it.
A terminal on the device from your browser, even behind the shop's router — a reverse tunnel over the connection it already holds. It reaches only what the device itself offers, never another machine on the network. Ordinary SSH from the shop's network stays shut behind the device's firewall until you open it from the same tab, for a set time.
ArdaForm is under active development. Most of it is running on deployed hardware right now; some of it is a design we haven't finished. Here is the split.
| Piece | Status | Notes |
|---|---|---|
| ArdaPlayer runtime | Working | Pure-Go binary, WPE WebKit on the bare display, x86-64 and ARM64, in production on Raspberry Pi tablets and an x86 till. |
| git push → device | Working | GitHub App, per-branch connections, server-side packing, signed instructions, staged apply with the app choosing the moment. |
| Datasets, outbox, files, settings | Working | Sealed on the device, partition-scoped, gzip on the wire, at-least-once outbox, content-addressed files. |
| Device images & USB installer | Working | Raspberry Pi image, PC image, installer stick with a touch install app. Published from the portal's Downloads. |
| Adoption: code, LAN, Bluetooth, install codes | Working | Activation code on screen; same-network adopt; Web Bluetooth with Wi-Fi hand-over; install codes with optional approval. |
| Android player | Working | The same runtime as an Android app — one APK for tablets, displays and TV boxes (Android 7 or newer; arm64, armv7, x86-64), downloaded from this site and the portal’s Downloads, not from Google Play. Activation, sync, Wi-Fi printers, the battery and the portal’s device page work as on Linux; a box set up as device owner gets kiosk mode from the portal. Installing it. |
| Remote support | Working | Log capture, screen pictures, console, screenshots, sliders, reverse SSH, peripherals tab, alerts per device. A firewall on every device; External SSH opened from the portal for a set time, with keys installed from there. |
| Player self-update | Working | Pushed as a signed instruction, tried once before it is armed, three-start rollback guard. |
| Printers, serial, scanners, screens, audio | Working | Raw ESC/POS, ZPL, Star, TSPL and ESC/P (dot-matrix) printers; USB-serial; keyboard-wedge readers; backlight and DDC/CI; ALSA volume. |
| Cameras on screens | Working | RTSP and IP cameras shown live in the app — the camera's own video, hardware-decoded where the board can, with a motion-JPEG fallback. |
| Webhooks | Working | The app calls your server; ArdaForm makes the request — signed when you give it a key, verifiable when Verify is on — and logs every delivery. The key never reaches a device. |
| Public sign-up | Working | Anyone can create an account on the order page. The free plan needs no card; Basic and Pro are paid by card. Sign in with a password, or with Google or GitHub. |
| Public Bluetooth setup page | In progress | A device with no network already points to ble.ardaform.net, where a phone gives it a Wi-Fi network (ArdaPlayer v1.2.3). Changing the Wi-Fi of a device that is online, behind the device's password, is not built. |
| Marketplace | In progress | Listing an app from a project's tab and installing it from the shop front work. Paid apps — per device or per install; monthly, yearly or one-off — are paid to the seller's own Stripe account. A per-device app is bought as licences: more at any time, charged for the rest of the period; fewer from the next renewal. Built and tested in Stripe's test mode; real payments for apps are not switched on yet. |
| GPIO, camera capture, face matching | Planned | Designed around; not started. (Showing a network camera already works — above.) |
ArdaPlayer is the part that actually meets the hardware — one Go binary, a WebKit surface on the bare display, and a deliberately narrow bridge between them.