Skip to content

Architecture ​

The single most important mental model in WebToApp: preview and export are two different execution paths that share the same runtime code. Most bugs of the form "works in preview, broken after export" come from breaking this contract.

The two paths ​

text
Editor (Compose screens in app/)
  ↔ data models (WebApp, configs)
  ↔ export factory (ApkConfig / ApkConfigJsonFactory)
  ↔ ApkBuilder / ApkBuildCache  →  signed generated APK

app/ sources
  → syncShellRuntimeSources  →  shell DEX  →  webview_shell.apk (template)

Generated APK runtime
  WebToAppApplication → ShellModeManager → load assets JSON config
  → WebViewManager / runtime servers (Node/PHP/Python/Go/WordPress)
Host :app (preview)Generated APK (export)
DEXAll app/src classesShell-synced subset (full runtime set)
ConfigEditor / in-memory modelsAssets JSON via ShellModeManager
TemplateNot usedapp/src/main/assets/template/webview_shell.apk

The contract ​

A flag set in the editor is useless at export unless it flows through all of:

  1. Model — WebApp / nested config, bound to the editor UI.
  2. Export mapping — ApkBuilder / ApkConfig / ApkConfigJsonFactory.
  3. Shell config types — ShellModeManager / shell config data classes (if the runtime reads it).
  4. Runtime use site — in shell-synced code.

Miss any step and you get one of three symptoms: the editor shows a switch that export ignores, export embeds config the runtime never reads, or the runtime reads a field that was never written.

One shell template ​

There is exactly one shell template: webview_shell.apk from :shell release. Do not introduce a second template APK. The shell ships minSdk 23 / targetSdk 35 and the synced runtime is adapted to target 35 (runtime permissions, FGS types, exact-alarm fallback) — keep those paths working if the value moves again. ApkExportConfig.targetSdk can pin a different target per app; ApkExportConfig.minSdk can raise the floor (never below 23).

Configuration center ​

The single source of truth for all feature settings is WebApp (data/model/WebApp.kt) and its *Config classes, carried through a full packaging passthrough chain into the generated APK. At runtime, the generated app reads its config from app_config.json in assets via ShellModeManager.

Dependency policy ​

Avoid new third-party dependencies unless strongly justified (app/build.gradle.kts / shell/build.gradle.kts). Prefer platform APIs and existing modules. The shell has a thin dependency set — keep it that way.