-
Notifications
You must be signed in to change notification settings - Fork 0
Mobile and Offline
Getting Forge onto a phone is two separate decisions — which of the two mobile surfaces you deploy, and what you expect to happen when the network drops. They are related, because the honest answer to "does it work offline" depends on which one a worker is holding. This page draws that line, since it is the fact a floor rollout is most often planned wrongly around.
Canonical references: docs/functional-reference/offline.md for the caching and queue mechanics, and docs/mobile-app.md in forge-deploy for what the server side of a native rollout needs. Both are worth reading after this page, with one caveat noted below. For the wider map of entry points see App Surfaces; for the fixed terminal on the floor, Shop Floor Kiosk.
Install the web app. The web manifest declares a standalone, portrait application whose start URL is the worker view — so installing Forge from a phone browser gives a home-screen icon that opens the floor UI (clock, jobs, scan, hours, chat, notifications, account), not the desktop shell. There is nothing extra to deploy: it is the same origin, the same container and the same login as the office app. A touch device on a narrow viewport that hits the root URL is redirected to the worker view anyway, unless the user has explicitly chosen to view the desktop site — see App Surfaces.
The native shell. A Capacitor build for Android and iOS whose web assets ship inside the binary and which deliberately hard-codes no server address: a build is not tied to an instance. First run opens a camera viewfinder for an enrollment QR code that an admin generates from the install (Admin → Devices), with a typed server address as the escape hatch. On the manual path the phone fetches the instance's public discovery document to learn the API base, the instance name, the accepted sign-in methods and the minimum app version it will accept.
The native path has server-side prerequisites the web path does not:
| Setting | Why it matters |
|---|---|
MOBILE_INSTANCE_NAME |
The name a worker sees while the phone is connecting. Make it recognisable. |
MOBILE_CERT_SHA256 |
The fingerprint of your edge TLS certificate, pinned trust-on-first-use. The API cannot see the certificate because TLS terminates at the proxy, so you set this — and you set the new value here before the certificate rotates, or enrolled phones refuse to connect. |
MOBILE_MIN_APP_VERSION |
Phones on an older build are told to update rather than allowed to run against an API they do not match. |
TLS is mandatory on this path — the app refuses a plain http:// server outright. And every mobile capability ships off: CAP-MOBILE-CORE enables enrolment, device-bound token refresh, the device registry and remote revoke; one capability per screen layers on top (scan, clock, jobs, stock, lookup). An install that turns none of them on accepts no enrolments at all. See Capability Gating.
Crash reporting is optional, self-hosted and off unless you stand up the sidecar and set its DSN; phones read that address from the same discovery document, and each phone has its own opt-out. Nothing about the mobile app reports to Armory Works.
After enrolment a personal device sets a local numeric PIN, optionally backed by device biometrics, stored in the platform's secure storage. It locks on idle and on cold start, using an idle timeout the app fetches from the instance per role — floor-tier roles get a long working-shift timeout, office-tier roles a short one — and repeated failed unlocks wipe the device's local credentials.
The part worth telling workers plainly: locking hides the app. It does not sign you out, and it does not discard queued work. Unlocking returns you to where you were, pending changes intact.
A device enrolled as shared skips the personal lock entirely. A shared phone or tablet is not one person's; workers identify per transaction the way they do on a kiosk, and the device itself carries a token that the API validates on every request — revoking the device in the admin registry causes the next request to fail closed and the app to wipe its local credentials. That revoke is the control you use when a phone is lost, and it is immediate rather than waiting for a token to expire.
Which screens the native app shows is capability-gated per install; the account screen is always present so a worker can always reach their own settings, diagnostics toggle and problem report.
Two different mechanisms are both called offline, and they apply to different surfaces.
Read caching — every production browser build. The Angular service worker prefetches the app shell, so the app opens with no network at all, and caches API reads freshness-first: it tries the network, and falls back to the cache when the network does not answer inside a short timeout. Lookup data — customers, parts, track types, reference data, terminology — is held longest with the tightest timeout, because it changes rarely and every form dropdown needs it; other reads are held for a much shorter window. ngsw-config.json in forge-ui is the authority on the exact groups and durations.
That makes the app load and show recent data. It does not let you save.
The write queue — the native shell only. The offline queue is IndexedDB-backed, and a mutation is queued rather than sent only when the build is the native mobile shell and the device is offline. In a browser, including an installed PWA, the same call goes straight to the network and fails like any other request. The queue is also scoped: it stands behind the shell's own API surface, which is a deliberately small set of floor actions — advance a job (and the compensating move back), start and stop a timer, add a job note (and remove it), a clock punch and its undo, and a stock move. Scan resolution, lookups, on-hand checks and photo attachment are online-only even in the native app.
Queued mutations carry the same idempotency key they would have sent live, so a replay after reconnect cannot double-post — see API Access for the server side of that contract. The queue drains oldest-first when the device comes back online or when the app returns to the foreground. A server refusal parks the entry in a dismissible rejected list, on the assumption the fix happens on a full screen rather than on a phone. A conflict pauses the drain and asks the worker to keep theirs or keep the server's, rather than guessing; docs/ux/concurrency-conflict-ux.md covers the same decision on the desktop. A banner on every surface shows offline, syncing, or all-synced with a pending count.
One caveat when you read the repo's offline reference: its worked enqueue example uses a generic endpoint to illustrate the service's API. It describes what the queue can store, not a path that is wired up — the queued set is the floor actions listed above and nothing else.
On browser surfaces the service worker keeps serving the cached build until every tab of the app is closed, which means an ordinary refresh — even a hard one — can leave a user on the old version. Forge handles this rather than leaving it to chance: the app polls for a new deployment and, when one is ready, shows a prompt that stays put until the user takes it and reloads at a safe moment, instead of swapping the app out mid-edit.
Operators should know this exists, because the failure mode without it is that a shipped fix looks undone to anyone who has not reloaded. If you deploy a fix and a user still reports the old behaviour, ask whether they took the reload prompt before you go looking at Operations and Troubleshooting. Native shells update through the platform's own store or distribution channel instead, which is what MOBILE_MIN_APP_VERSION is for.
Forge · Apache 2.0 · built by Armory Works — this wiki maps the docs; the authoritative detail lives in docs/.
Evaluating
Running it
- Installation
- First Week
- Configuration and Integrations
- Hardening a Production Install
- Backup and Restore
- Upgrades and Rollback
- Accounting Modes
Using it
- App Surfaces
- Shop Floor Kiosk
- Mobile and Offline
- Access and Roles
- Customizing an Install
- Feature Reference
- UI Flows
Building on it
- API Access
- Architecture
- Capability Gating
- Workflow, Gates and Approvals
- Data Ownership and Export
- Glossary
Contributing
Repo wikis