doxa-maps/documentation/how-to-build-mobile-apps-from-plugins/README.md
Doxa Maps f3fdf4bf37 Mobile apps from plugins: a how-to, with Deep Research as the worked example
documentation/how-to-build-mobile-apps-from-plugins/README.md explains why Deep Research
(doxa-maps-spa, its app preset) is the plugin to wrap first: the seven production maps in one
phone-ready shell, token-free on MapLibre. It then walks the whole path: tools, the wiring check,
one command, what each step does, another plugin as the app, making it your own, and fixes.

The one command needed two small changes; the default app is unchanged:
- internal/set-app-start-page.mjs takes APP_START=<plugin>/<screen>[/<preset>] and opens that page
  instead of the UPG-100 list. Unset, it behaves and marks the page exactly as before. A malformed
  value, a page missing from the build, or links that would not resolve are refused, as before.
- package.json: phone:from-tree is sync, start page, verify, assemble, install from the committed
  tree, with no full rebuild (bun run build refuses without BUILD_ALLOW=1).
  phone:deep-research is phone:from-tree with Deep Research as the start page.

how-to.md links the guide, and two of its lines are corrected: webDir is public/dx-maps/, and
apk:debug's first step is the full build, which asks for BUILD_ALLOW=1.

Checked, with no Android tools: the start page written for doxa-maps-spa/doxa-maps-spa/app, then
the app root served and loaded in the shared browser at 390 and 1280. It showed the gallery
element, 15 tabs (the seven maps and the experimental ones) and a drawn map, with 0 console errors
and 0 failed requests. --check passed for APP_START and failed for the default until it was
restored; the default run still writes the UPG-100 page with its original marker. The Gradle and
adb steps are those bun run phone already uses; they were not run here.
2026-09-30 10:04:34 +00:00

5 KiB

How to build a mobile app from a plugin

The plugins in this repo are web pages, and an Android app can wrap them with no new code. This guide turns one into an app you can install, using Deep Research as the worked example. It takes one command once the tools are installed.

Why start with Deep Research

Deep Research is the plugin that is already a whole app. It is the app shell in plugin-designs/doxa-maps-spa/ (its app preset). One screen holds all seven production maps:

  • Big Picture;
  • Simple Research;
  • Regions;
  • Prayer Progress;
  • UPG-100 List;
  • Cities with Internet;
  • Gospel Resources.

The experimental maps are there too. It is made for phones:

  • a round ☰ at the bottom left switches maps;
  • each legend starts folded;
  • the ⓘ opens as a sheet over the map;
  • posters, packets and cards print from the phone.

It draws with the free MapLibre engine, so it needs no Mapbox key. And it needs no new code: the app is the same built folder the web uses, opened on Deep Research instead of on the Plugin Studio.

The short version

bun install
bun run check:mobile          # checks the app is wired up; needs no Android tools
bun run phone:deep-research   # makes the app and installs it on your phone or emulator

Then open Doxa Maps on the phone.

What you need

  • This repo, cloned, and Bun. The README's quick start covers both.
  • Android Studio, which brings the Android SDK and adb, and JDK 17.
  • An Android phone plugged in over USB with USB debugging turned on, or an emulator started from Android Studio. adb devices should list it.

iOS is not set up yet. It needs a Mac with Xcode, and its project would live beside the Android one, at deployment/capacitor/ios.

Step by step

1. Check the wiring (no Android tools needed)

bun run check:mobile

This copies the built folder, public/dx-maps/, into the Android project (Capacitor's cap sync). It then checks that the copy landed. It should end with OK webDir copied.

2. Make the app and install it

bun run phone:deep-research

This runs, in order:

  1. cap sync android: copies the built folder into the Android project.
  2. The start-page step, APP_START=doxa-maps-spa/doxa-maps-spa/app: the app opens Deep Research instead of the Plugin Studio.
  3. cap:verify: stops if the copy is empty, which would show as a blank white screen.
  4. ./gradlew assembleDebug: builds app-debug.apk.
  5. adb install -r: installs it on the phone.

It uses the built folder as it is committed, so nothing is rebuilt. On a fresh clone that folder is the current build.

3. Open it

The app is called Doxa Maps. On a phone it opens on Simple Research, because Big Picture needs a larger screen. The round ☰ at the bottom left lists every map.

Changed a plugin first?

Rebuild the one you changed, then run the same command:

BUNDLE=<plugin> bun x vite build && bun run tree && bun run fix:sri
bun run phone:deep-research

Any other plugin as an app

It is the same command with another start page. Name the page's folder inside public/dx-maps/, as <plugin>/<screen> or <plugin>/<screen>/<preset>:

APP_START=doxa-simple-map/doxa-simple-map bun run phone:from-tree   # Prayer Progress
bun run phone:from-tree                                             # unset: the UPG-100 list

Pick a page that works on a phone; Big Picture, for one, is desktop only. The start-page step refuses a page that is not in the build, and one whose links would not resolve at the app's root.

Make it your own

  • The name under the icon: app_name in deployment/capacitor/android/app/src/main/res/values/strings.xml.
  • Icon and splash screen: the images in deployment/capacitor/android/app/src/main/res/.
  • Version: versionCode and versionName in deployment/capacitor/android/app/build.gradle.
  • A store release: it needs its own app id and a signing key. The key never goes in the repo.

If something goes wrong

  • A blank white screen: the copy is empty. Run bun run check:mobile; it must say OK webDir copied.
  • The app opens the Plugin Studio: the start-page step did not run. Run bun run phone:deep-research again.
  • adb finds no device: turn on USB debugging and accept the prompt on the phone, or start an emulator.
  • Maps without their data: several maps load live data, so the phone needs internet.
  • Using a Mapbox token: the app's address is https://localhost. A token service must allow that address (CORS). Deep Research's app preset uses MapLibre and needs no token.

How it works

The app is a WebView around the same built folder the web serves; capacitor.config.json points at it (webDir). The start-page step, internal/set-app-start-page.mjs, copies the chosen page to the folder's root in the app's copy and fixes its links. So the app opens that page, and the web folder itself is untouched. The Plugin Studio stays inside the app at studio.html.

One build, three outputs: the web folder, this Android app, and the desktop app (see the README).