Skip to main content

Ubuntu Touch shell strategy — webapp delivery without UI rewrite

Tier: Public
Status: Decision-of-record 2026-05-31
Audience: core team, module authors, self-hosting operators, Ubuntu Touch integrators, plan executors
Builds on: PLATFORM-ARCHITECTURE.md §1.1, CROSS-PLATFORM-BOUNDARIES.md, AUTH-STRATEGY.md, canonical-native-platform-surface.md, application-surfaces-vs-platform-backbone.md, ROADMAP.md standing principles
Resolves: whether Umbraculum modules can reach Ubuntu Touch without a Qt/QML rewrite; what portability means for canonical and vertical modules on Lomiri
Referenced by: CROSS-PLATFORM-BOUNDARIES.md §9, PLATFORM-ARCHITECTURE.md §1.1 / §3.5, ROADMAP.md standing principles, MODULES.md §5.1, canonical-native-platform-surface.md §3.4

Disclaimer. This document records a delivery strategy, not an implementation commitment with dates. It does not allocate a new canonical module, does not change licenses, and does not weaken the native-slice offline guarantees on iOS/Android. It explicitly accepts online-first behavior on Ubuntu Touch in exchange for fast store presence and zero Tamagui duplication.

Terminology. Vertical and brewery follow GLOSSARY.md: a vertical configuration is a specific product built on Umbraculum; brewery is the reference vertical shipped in this monorepo (Tier 6), not the platform's identity. Where this doc says brewery vertical, read brewery (reference vertical) unless a narrower brewery-domain rule is meant.


1. Summary — the decision

QuestionDecision
Can React Native run natively on Ubuntu Touch?No — no maintained RN target for Linux mobile; not planned by Meta or Microsoft.
Can we ship Umbraculum on Ubuntu Touch without rewriting UI in Qt/QML?Yes — via the UT Morph webapp wrapper: a Lomiri Click package that wraps apps/web in Morph's Qt WebEngine webview (webapp-container).
Do we maintain Tamagui as the single UI primitive layer?Yes — non-negotiable. Ubuntu Touch consumes the web slice, not a parallel QML tree.
Do we require OpenStore / Click store presence?Yes — non-negotiable. Packaging is a first-class deliverable, not "open in Morph manually."
Do we require offline on Ubuntu Touch?No — explicitly sacrificed for now. Online-first is an accepted trade-off on this delivery path.
What is the strategic payoff?Faster React-app delivery across web + iOS/Android native + macOS (via web or future RN macOS) + Ubuntu Touch from one Tamagui/Next source tree — without forking the module model.

Way forward (precise): treat Ubuntu Touch as a fourth workspace web UI that reuses apps/web unchanged, distributed as a UBports webapp Click package per deployment (self-hosted URL or hosted product URL). Domain logic stays in API + contracts; UI stays in Tamagui web pages.


2. Discourse record — how we got here

This section names the full reasoning chain so future readers do not re-litigate rejected paths.

2.1 Starting question

Is there a way to make React Native work on Linux phones, or will it be possible in the future?

Finding: Official React Native targets iOS and Android. Out-of-tree platforms include Windows, macOS, tvOS, visionOS, and Web — not Linux mobile. Canonical's 2016–2017 Ubuntu Touch RN fork is archived. Microsoft has stated no plans for Linux in react-native-windows. Community RN-on-Linux-desktop experiments (Skia renderer, Qt desktop port) do not constitute a phone platform.

Implication for Umbraculum: "RN on Ubuntu Touch" is not a credible product path.

2.2 Umbraculum-specific reframing

Can a canonical or vertical Umbraculum module appear on Ubuntu Touch without rewriting everything in Qt?

Umbraculum modules (RFC-0002) are four coordinated slices:

SlicePortable to UT without rewrite?
Contracts (@umbraculum/<code>-contracts)Yes — MIT npm, Zod, route IDs
API (services/api/src/modules/<code>/)Yes — HTTP
Web (apps/web/app/[locale]/(<code>)/)Yes — runs inside Morph webview
Native (apps/native/src/modules/<code>/)No — Expo targets iOS/Android only

The toolset commitment (PLATFORM-ARCHITECTURE.md §1.1) is one source of truth → web + native (RN/Expo), with Tamagui bridging DOM and RN. A Qt/QML port would fork the UI slice and violate CROSS-PLATFORM-BOUNDARIES.md §3 ("shared screens must not import platform frameworks") and OPEN-SOURCE-STACK.md rationale (Flutter = rewrite; separate native stacks = double maintenance).

Implication: Full Qt rewrite is infeasible by design and not aligned with the module model.

2.3 Three portability layers (mental model)

  • Layer 1 (API + contracts): fully portable; any client can integrate.
  • Layer 2 (navigation, i18n, api-client): portable to JS/TS clients; UT webapp inherits these via the web bundle.
  • Layer 3 (Tamagui screens): portable between web and RN today; UT joins via web, not a third widget toolkit.

2.4 Options considered

OptionRewrite?Store presence?Offline?Verdict
A — UT webapp → apps/webNoYes (Click)NoSelected
B — UT webapp + auth bridge extensionsNo (small API glue)YesNoFollow-on enhancement
C — Contracts + bounded QML clientPartial UI rewriteYesPossibleRejected as platform strategy; tier-3 integrator path only
D — Waydroid / Android layerNoAwkwardYes (RN slice)Personal hack; not product distribution
E — React Native on UT nativelyN/AN/AN/ANo maintained path
F — Full Qt/QML module UIYes — all screensYesPossibleRejected — forks module model

2.5 Non-negotiables (confirmed feasible)

The selected path satisfies both constraints from product direction:

  1. No rewrite / maintain Tamagui — UT shell loads existing Next.js + Tamagui pages; no QML screen tree, no second component library.
  2. Store presence — UBports documents first-class webapp Click packages: Lomiri icon, AppArmor confinement, OpenStore distribution via webapp-container + Morph (Qt WebEngine).

Sacrificing offline on Ubuntu Touch is explicitly accepted to unlock quick delivery and an overall boost in React-app reach (web, iOS, Android, macOS-class browsers, UT) from one UI investment.


3. Why this choice — rationale

3.1 Aligns with existing architecture

  • Application surfaces (application-surfaces-vs-platform-backbone.md): workspace web UI = apps/web + apps/native. UT webapp is apps/web + a packaging adapter, not a new backbone layer.
  • Route policy (CROSS-PLATFORM-BOUNDARIES.md §2): routes already have stable RouteIds and web paths via @umbraculum/navigation. UT navigates locale-prefixed URLs (/en/products, /en/vessels, …) — no new route semantics required.
  • Auth (AUTH-STRATEGY.md): web uses cookie sessions (sid). UT webapp is a web client; standard login flows apply. Optional follow-on: extend the existing webview-exchange bridge for smoother handoff from a future UT-specific entrypoint.
  • Native slice unchanged (canonical-native-platform-surface.md): iOS/Android keep bearer auth, offline roadmap (SQLite), and brew-day guarantees. UT does not dilute those commitments.

3.2 Aligns with ROADMAP posture

ROADMAP.md already states web-first for heavy desktop workflows and contemplates web + PWA fallbacks where native is not justified (e.g. WMS). UT webapp delivery is consistent with that pattern — another online-first web delivery for operator workflows that do not require device-local persistence.

3.3 Rejects fragmentation

RFC-0001 §2 names domain duplication and cross-cutting fragmentation as core failure modes. A Qt UI fork would recreate Magento-style parallel implementations per platform. The Morph webapp wrapper keeps one UI slice per module.

3.4 Strategic velocity

Product view: optimize for time-to-Ubuntu-Touch, not parity with native offline. Each module that ships Tamagui web pages is UT-ready once packaged — no per-module Lomiri engineering. That accelerates the same React investment across:

  • Web (all browsers)
  • iOS / Android (Expo native slice where warranted)
  • macOS (Safari / future RN macOS / web)
  • Ubuntu Touch (Morph webapp)

4. What Ubuntu Touch delivery is (precise definition)

4.1 UT Morph webapp wrapper

A Click package containing:

  • manifest.json — app name, version, framework target
  • .desktop launcher — Exec=webapp-container ... with start URL and URL patterns
  • AppArmor policy — typically networking, webview, and related groups per UBports Click docs
  • Icon assets for Lomiri dash / OpenStore

At runtime:

  1. Operator taps the app icon on Lomiri.
  2. webapp-container opens the configured apps/web base URL (e.g. https://ops.example.com/en/dashboard) in Morph's Qt WebEngine webview.
  3. Tamagui pages, module routes, cookie auth, and AI consultant UI behave as on desktop web (within webview capabilities).

No Umbraculum TypeScript runs on the device except what the web bundle delivers over HTTPS.

4.2 Relationship to the four β slices

SliceUT webapp role
ContractsUnchanged — still the third-party pin surface
APIUnchanged — webview calls same Fastify routes
WebPrimary UT UI — zero fork
NativeNot used on UT — offline/sync guarantees do not apply to this delivery path

4.3 Reference Click package (packaging artifact)

RFC-0002 defines four runtime slices per module. For UT distribution the repo ships an optional packaging artifact (not a fifth runtime slice):

PathRole
packaging/ubuntu-touch/umbraculum-reference/Reference Click webapp — manifest, AppArmor, webapp-container launcher, icon
scripts/ubuntu-touch/render-click-desktop.shRepo-root wrapper; sets UMBRACULUM_WEB_ORIGIN then renders umbraculum.desktop

Tier-3/self-host authors copy that folder, change origin env vars, click build. No @umbraculum/*-contracts or module-sdk changes.

See also packaging/ubuntu-touch/README.md.


5. Accepted trade-offs

5.1 Sacrificed on Ubuntu Touch (explicit)

Column key: UT webapp (v1) is the Lomiri Click + Morph shell over apps/web only. Why not in UT v1 webapp states the feasibility/cost reason — not a moral judgment, but what we deliberately did not pay for in the first UT delivery tranche.

CapabilityiOS/Android nativeUT webapp (v1)Why not in UT v1 webapp
Offline SQLite / brew-day loggingPlanned / product guarantee for the brewery reference vertical on iOS/Android (brewery IMPLEMENTATION-LOG)Not supportedOffline is owned by the native slice (device SQLite + sync queue — DATA-ACCESS-BOUNDARIES.md §5). v1 UT has no native slice and no second on-device store. Shipping offline in Morph would mean new client persistence + conflict rules beside the existing native plan — high cost, two offline stories, slow vs “wrap apps/web now.” Accepted trade: online-first on UT.
Bearer-only native auth transportYes (POST /auth/login/native, Secure Store)Cookie web session (sid in Morph)apps/web is already cookie-session (AUTH-STRATEGY.md). Bearer-in-webview would need custom token injection + refresh handling in the Click shell with no product win over standard web login for v1. Accepted trade: UT behaves like web auth, not Expo auth.
Push notifications (Expo)Future native path (FCM / APNs via Expo)Not in v1 webapp wrapperPush requires native registration (device token, OS notification channel). A Morph webapp is not an Expo app; Lomiri-visible push would need UBports-specific glue (Click lifecycle, system notifier, optional small Qt helper) — separate from Tamagui/web work. Deferred: possible v2+; not free with webapp packaging.
BLE / device sensors via native modulesNative-only (apps/native + RN plugins)Not in v1 webapp wrapperSensor/BLE code lives in the RN native slice, not in Tamagui web. Web Bluetooth inside Morph is unreliable or absent for industrial use; a Lomiri-native BLE bridge would be a new bounded client (Option C in §2.4), not “no rewrite.” Deferred: integrator or v2; out of quick-delivery scope.
Background sync queueNative roadmap (pairs with offline SQLite)Online only — no background drain queueA sync queue exists to flush local writes when connectivity returns. Without UT offline storage, there is no queued work to replay in background — only live HTTP while the webview is open. Accepted trade: same as browser tab; no native WorkManager-style pipeline in v1.

Feasibility framing (outside the table)

The v1 UT path optimizes for one cost profile:

If we paid for…Rough costWhat we would give up
UT offline parity with iOS/AndroidSecond client persistence layer + sync semantics + tests; likely touches API conflict rules“Quick delivery” and single offline owner (native slice)
UT push / BLE in v1Lomiri-native or Qt bridge work per capability, ongoing UBports QATamagui-only, no-rewrite constraint
Qt/QML module UI instead of webappFull UI rewrite per moduleEntire cross-platform toolset story

Feasibility verdict: v1 UT is feasible and cheap precisely because it reuses the web slice and accepts the rows above. Each “not in v1” row is technically possible later only if we accept new cost (native glue, new slice, or abandoning online-first). None of them are blockers to shipping operator UI on OpenStore today; they are scope boundaries, not unknown engineering.

Brewery on UT: operators get web workflows (recipes, water, inventory read-only where web ships, automation dashboards, PIM admin, MRP/CRP read views). They do not get the native brew-day offline guarantee on Lomiri. That is an intentional product boundary, not a gap to paper over.

5.2 Retained on Ubuntu Touch

  • Full Tamagui operator UI for every web-shipped module route
  • OpenStore / Click installability
  • Workspace auth, billing, AI consultant (online)
  • Canonical module semantics via same API + contracts
  • Single codebase for web + UT UI

5.3 Known webview limits

Morph uses Qt WebEngine (Chromium-derived, lagging desktop Chrome). Expect:

  • Responsive layout reliance (Tamagui already targets multiple widths)
  • Possible gaps vs latest PWA APIs (service worker depth varies)
  • File upload/download via ContentHub (UBports handles many cases — verify per workflow)

These are UX polish issues, not blockers to the strategy.


6. Module and vertical eligibility

Default rule: if the route is available on web, it is UT-webapp-eligible when online.

SurfaceUT webapp fitNotes
Platform (login, workspace select, dashboard)StrongEntry URLs for Click package
automationStrongVessels, telemetry — web-only on native today anyway
pimStrongAdmin catalog — web-only on native today
mrp / crpStrongRead-only alpha — web is primary
wms / crm (future)StrongROADMAP web-first bias
brewery reference verticalPartialWeb routes yes; native-only brew-day offline flows no (reference vertical product rules — not a platform-wide UT limitation)
Document rendering (RFC-0007 jobs)StrongAsync jobs + download — same as web
Native-only screens (getRouteAvailability(_, "native") === "available")Not in UT shellUse iOS/Android for those flows

Source for native vs web route matrix: canonical-native-platform-surface.md §3.


7. Multi-platform delivery map (operator surfaces)

Velocity claim (precise): adding or updating a web module page advances browser + UT simultaneously. Native screens remain a separate, justified investment for offline/mobile-only workflows — not a prerequisite for UT presence.


8. Explicit non-goals

  • No Qt/QML Umbraculum UI in core or canonical modules.
  • No React Native port to Lomiri — not maintained; out of scope.
  • No requirement that UT match iOS/Android offline semantics.
  • No parallel session model — UT uses web cookie auth; does not invent a third auth transport in v1.
  • No @umbraculum/navigation platform fork required for v1 — UT consumes web URLs; optional future AppPlatform extension is not blocking.
  • No core-team obligation to ship Click packages for every self-hoster — document the pattern; reference template at packaging/ubuntu-touch/umbraculum-reference/ for demo/self-host forks.

9. Implementation follow-ons (ordered, not scheduled)

These are enhancements to the decided strategy — not alternatives to it.

#Follow-onPurposeStatus
1Reference Click package for demo/hosted URLProve OpenStore path; template for tier-3 authorsShipped: packaging/ubuntu-touch/umbraculum-reference/
2Responsive / touch UX pass on high-traffic web routesThumb reach, Lomiri safe areas — still Tamagui, not QMLOpen
3Auth polish — webview-exchange entry URLOptional deep-link login without retyping credentialsOpen
4@umbraculum/navigation — optional touch_web platform tagDocument route policy per shell; no UI forkOpen
5Self-host runbook sectionURL configuration, TLS, Click rebuild on URL changePartial — see reference package README
6CI smoke — Morph/QtWebEngine not in CIManual device checklist only (documented)Open

10. Verification checklist (strategy acceptance)

Before declaring a UT deployment "aligned with this doc":

  • UI served from apps/web — no QML duplicate of module screens
  • Click package installs from OpenStore or click install (build from packaging/ubuntu-touch/umbraculum-reference/)
  • AppArmor allows HTTPS to the configured API/web host
  • Cookie login completes inside webview
  • At least one canonical module route and one vertical route verified online on device
  • Documentation states online-only for UT; offline messaging not shown misleadingly

DocRelevance
README.mdDocs index — Design + Architecture entries
PLATFORM-ARCHITECTURE.md §1.1, §3.5Cross-platform toolset commitment
MODULES.md §5.1Four β slices; UT uses web slice only
CROSS-PLATFORM-BOUNDARIES.md §9UT workspace web UI summary
application-surfaces-vs-platform-backbone.mdWorkspace web UI layering
AUTH-STRATEGY.mdCookie vs bearer split
DATA-ACCESS-BOUNDARIES.md §5Native offline vs UT (no SQLite on UT)
ROADMAP.mdStanding principle — UT Morph webapp wrapper
canonical-native-platform-surface.md §3.4What stays iOS/Android-only
modules/verticals/brewery/IMPLEMENTATION-LOG.mdBrew-day offline — native only (brewery reference vertical)
GLOSSARY.mdVertical, canonical, brewery-as-example convention
TAMAGUI.mdUI primitive layer preserved on UT via web
NATIVE-STRATEGY-AND-CI.mdExpo native — orthogonal to UT shell
OPEN-SOURCE-STACK.mdRN vs Flutter rationale + UT note
rfc-companion-documentation-audit.mdCompanion doc maintenance row
packaging/ubuntu-touch/umbraculum-reference/README.mdReference Click webapp — build / install / fork
scripts/ubuntu-touch/render-click-desktop.shRender .desktop from origin env vars
UBports webapp guideUpstream webapp-container reference
UBports Click packageAppArmor, manifest, .desktop

12. Resolution

Decision: Ubuntu Touch is a Morph webapp wrapper target reusing apps/web + Tamagui, distributed as Click/OpenStore packages, online-first, no Qt rewrite.

Rejected: full QML UI port, RN-on-LUT, Waydroid-as-product-strategy, offline parity on UT in v1.

Trade accepted: no offline on Ubuntu Touch → faster unified React delivery across web, iOS/Android native, and Lomiri store presence.

Changes to this strategy require the same discipline as other design-of-record docs: propose an amendment PR with explicit trade-off review; do not silently expand scope into QML or offline without a new decision section.