The Problem

Developers and power‑users often need a quick way to package a web page (or a small web app) as a native Android APK without installing Android Studio or writing Java/Kotlin code. Existing solutions require a desktop build environment, manual signing, and custom wrapper code, which adds friction for rapid prototyping or distribution.

What This Does

web-to-app is an Android application that lets a user type a URL, selects optional AI‑generated assets, and produces a signed, encrypted APK directly on the device. The core conversion logic lives in the Kotlin package com.webtoapp.core.

  • app/src/main/java/com/webtoapp/ui/MainActivity.kt launches the UI, collects the target URL, and invokes ApkBuilder (see app/src/main/java/com/webtoapp/core/apkbuilder/ApkBuilder.kt).
  • ApkBuilder assembles a temporary Android project, copies the selected sample front‑end (e.g., app/src/main/assets/sample_projects/react-demo/dist/) and runs FrontendProjectBuilder (app/src/main/java/com/webtoapp/core/frontend/FrontendProjectBuilder.kt) to inject the URL into the web assets.
  • The final binary is encrypted with the AES‑GCM engine (app/src/main/cpp/crypto_engine.cpp + app/src/main/java/com/webtoapp/core/crypto/AesCryptoEngine.kt) and signed by JarSigner.kt.

All UI components (cards, dialogs, etc.) are pure Compose files under app/src/main/java/com/webtoapp/ui/components/, keeping presentation separate from the build pipeline.

How It Is Wired

  1. App launch – Android starts MainActivity (MainActivity.kt).
  2. User input – UI components call AppExporter.exportApp(url) (implemented in AppExporter.kt).
  3. Project preparation – AppExporter creates a FrontendProjectConfig and passes it to FrontendProjectBuilder.build(config). This builder copies the selected sample project from app/src/main/assets/sample_projects/*/dist/ into a temporary directory.
  4. URL injection – ProjectDetector scans the copied assets and replaces placeholder strings with the user‑provided URL (logic in ProjectDetector.kt).
  5. APK assembly – ApkBuilder.build(tempDir) creates the AndroidManifest, resources, and compiles the stub app using Gradle (app/build.gradle.kts).
  6. Encryption – Before signing, the generated APK bytes are fed to AesCryptoEngine.encrypt() which calls the native crypto_engine.cpp (via JNI declared in NativeCrypto.kt).
  7. Signing – JarSigner.sign(apkBytes) produces the final signed APK placed in the app’s private storage.

The widest blast radius lies in crypto_engine.cpp and AiApiClient.kt – they touch native code and external AI services, respectively, so changes there affect security and network behavior across the whole product.

How To Use It

# Clone the repository
git clone https://github.com/moses-y/web-to-app
cd web-to-app

# Build the Android app (requires Android SDK and Gradle)
./gradlew :app:assembleDebug   # produces app/build/outputs/apk/debug/app-debug.apk

No additional configuration files are required for a basic build. To run the app on a device, install the debug APK (adb install app/build/outputs/apk/debug/app-debug.apk) and launch it. Inside the app, enter a URL and tap Build APK; the generated file appears in the app’s “Export” folder.

Real‑World Use

A marketing team can ship a branded web landing page as an installable APK for events where Google Play distribution is unavailable. The workflow:

val url = "https://example.com/promo"
AppExporter.exportApp(url)   // invoked from a button in MainActivity

The resulting APK can be shared via QR code or NFC without any external build server.

Code Health & Issues

  • High – No test suite – 226 source files, 0 test files ([HIGH] Add a test suite).
  • High – Missing lockfile – app/src/main/assets/sample_projects/react-demo/package.json has no accompanying lockfile ([HIGH] Commit a lockfile).
  • High – No CI workflow – Repository contains no GitHub Actions or other CI config ([HIGH] Add a workflow that builds and tests).
  • Medium – Dependabot disabled – No automatic dependency updates ([MEDIUM] Enable Dependabot or Renovate).
  • Medium – Generated output committed – 27 build artifacts are tracked in app/ ([MEDIUM] Remove generated build output).
  • Low – Missing convention files – No .editorconfig, .gitattributes, or formatter config ([LOW] Add the repository convention files).

The static analysis also flagged deep nesting (up to 8 levels) in files such as crypto_engine.cpp and several AI‑related Kotlin classes, indicating a potential maintenance burden.

The Bottom Line

web-to-app delivers a functional on‑device pipeline for turning arbitrary URLs into signed Android APKs, with a clear separation between UI, build orchestration, and cryptographic handling. However, the lack of automated tests, CI, and reproducible JavaScript dependencies makes it risky for production use or downstream modification. It is best suited for internal prototyping or as a reference implementation for teams willing to invest in test and CI scaffolding.