CleanApp.app's mobile app to use the platform on mobile phones.
The software is developed using React Native, so if you encounter any issues because of React Native you can search additional information on public Reactive Native knowledge bases.
The full setup is currently available on MacOS only. The Android only build can be done on Linux as well. In that case you can skip iOS related steps in this README.
React Native
The first step to run the software is to setup React Native development setup on your machine. React Native has tutorials for different operating systems and mobile platforms here: https://reactnative.dev/docs/environment-setup
You can find detailed instructions on using React Native and many tips in its documentation.
Node.js
First you have to install node.js.
- MacOS: https://nodejs.org/en/download/package-manager#macos
- Linux, Debian based: https://github.com/nodesource/distributions?tab=readme-ov-file#installation-instructions
- General Linux: https://github.com/nodesource/distributions?tab=readme-ov-file
- Other approaches: https://stackoverflow.com/questions/39981828/installing-nodejs-and-npm-on-linux
Then install yarn.
sudo npm install --global yarn
Make sure the Node.js related software has versions as expected.
yarn -v # Expected to be >= 1.22.4
node -v # Expected to be exactly = v18.20.2
Use nvm to switch to a desired version.
nvm use 18.20.2
Android
Have Android studio installed
- Check that all available versions of CMake are installed
Make sure Jetifier is installed.
npx jetify
iOS
Make sure you installed XCode and Simulator
Please use an iPhone 12 or newer in the simulator as this is the minimum requirement right now.
Make sure you installed cocoa pod with version >= 1.10.1
pod --version
Change to the directory that you want to clone the code into.
git clone https://github.com/cleanappio/cleanapp-mobile.git &&
cd cleanapp-mobile
All environment variables are stored in the .env file in the project directory. The .env file is never to be pushed to git.
Take the .env file from the Google Drive CleanApp/Engineering/Mobile App Env folder. Ask project admins for the link. Copy the .env file into a project root directory.
- Open .env prepared in the previous step
- Modify the value of the APP_MODE variable. Set one of values:
local- for the local build & testing with backend running locally;dev- for build and testing with the backend running on dev cloud environment;prod- for production build;
-
Make sure the Mapbox download token is created.
- All public scopes are to be checked
- DOWNLOADS:READ from secret scopes is to be checked
The token can be taken from the .env file if it already exists.
-
Do platform specific setups
-
iOS
Create a correct .netrc file in your home directory so you can install the CocoaPods package for Mapbox. Here are tutorials that help to do that: https://github.com/mapbox/mapbox-gl-native-ios/blob/d89e7139e5f6a9a3ea5ad57782b41579b8a0bbb1/platform/ios/INSTALL.md#cocoapods Discussion about this on GitHub: mapbox/mapbox-gl-native#16581
Here is a schema for the ~/.netrc file:
machine api.mapbox.com login mapbox password <Download token> -
Android
-
Create the signing directory in your home directory.
mkdir $HOME/.signing -
Create the cleanapp.properties file in this directory
touch $HOME/.signing/cleanapp.properties -
Add the following line into the cleanapp.properties:
mapbox.downloadsToken=<Download token>
-
-
CleanApp uses a centralized version management system to ensure consistency across all platforms. NOTE: Please make sure to make the scripts executable by running the command: chmod +x <file_name>.(js/sh)
The app version is managed through version.json which serves as the single source of truth:
{
"version": "3.2.8",
"buildNumber": 21,
"versionCode": 39,
"description": "CleanApp version configuration - single source of truth for all platforms"
}# Patch version (3.2.8 -> 3.2.9)
npm run version:patch
# Minor version (3.2.8 -> 3.3.0)
npm run version:minor
# Major version (3.2.8 -> 4.0.0)
npm run version:major- Edit
version.jsonwith new version numbers - Sync across platforms:
npm run sync-version
For detailed version management documentation, see VERSION_MANAGEMENT.md.
yarn install &&
./patches/apply.sh &&
npx pod-install &&
yarn ios:bundle
There is no way to build and run on simulator from the command line due to error:0308010C:digital envelope routines::unsupported
- Run Metro
- Open a new terminal window
- Run command
yarn start
- Open Xcode
- In menu: File -> Open...
- Click the
ios/CleanApp.xcworkspace. The project will open - In menu:
Product / Clean build folder... - Choose
CleanApp > iPhone 14or any desired simulator on top of Xcode window in the center - In menu:
Product > Run
The application will run on the chosen simulator.
- Make sure you have Apple Developer account fully set. If you use org account you have to have dev privileges there.
- Update version numbers in
version.jsonand runnpm run sync-version - Run Metro
- Open a new terminal window
- Run command
yarn start
- Open Xcode
- In menu: File -> Open...
- Click the
ios/CleanApp.xcworkspace. The project will open - On the left panel click CleanApp, make sure General tab is opened.
- Choose CleanApp > Any iOS Device (arm64) on top of Xcode window in the center
- In menu:
Product / Clean build folder... - In menu:
Product > Archive - After build is done, an Archives window will be opened. Click Distribute App button. Follow prompts.
- Go to https://appstoreconnect.apple.com in browser, login and monitor build rollout.
yarn install && ./patches/apply.sh
CleanApp includes an interactive build script that simplifies the Android build process:
# Interactive mode - prompts for build type
./scripts/build-android.sh
# Command line mode
./scripts/build-android.sh debug # Debug build only
./scripts/build-android.sh release # Release build only
./scripts/build-android.sh both # Both debug and release
./scripts/build-android.sh --help # Show helpCleanApp supports a minimum-friction share flow on both iOS and Android:
X / browser / Reddit / etc. -> Share -> CleanApp -> report submits automatically
- No compose form
- No category picker
- No confirmation screen
- URL/text is preferred over image
- If URL/text and image are both present, the report is created from URL/text and the images are attached as supporting evidence
- Up to 6 shared images are supported
- If immediate submission fails, the payload is queued locally and retried later
Both platforms normalize inbound share payloads into the same native shape:
idcreated_atsource_appsource_urlshared_textlocal_image_pathsplatformsubmission_statefailure_reason
The payload is submitted to the backend endpoint:
POST /api/v3/reports/digital-share
The iOS implementation uses a native Share Extension:
- Target:
CleanAppShareExtension - Entry point:
ios/CleanAppShareExtension/ShareViewController.swift - Parser:
ios/CleanAppShareExtension/ShareParser.swift - Shared native queue/store:
ios/CleanAppShared/ShareModels.swiftios/CleanAppShared/ShareContextStore.swiftios/CleanAppShared/SharedDraftStore.swiftios/CleanAppShared/ShareSubmitter.swift
- Main app retry bridge:
ios/CleanApp/SharedDraftIngestor.swiftios/CleanApp/CleanAppShareModule.swift
App Group:
- App Group ID:
group.io.cleanapp.shared - Entitlements are added to both:
ios/CleanApp/CleanApp.entitlementsios/CleanAppShareExtension/CleanAppShareExtension.entitlements
Extension activation rules support:
- one web URL
- text
- up to 6 images
If provisioning is managed outside Xcode, make sure the App Group capability is enabled for both the main app and the Share Extension in the Apple Developer portal/App IDs.
The Android implementation uses a native share target activity:
- Entry point:
android/app/src/main/java/com/cleanapp/ShareReceiverActivity.kt - Parser:
android/app/src/main/java/com/cleanapp/ShareIntentParser.kt - Submission:
android/app/src/main/java/com/cleanapp/ShareSubmissionRepository.kt - Local draft store:
android/app/src/main/java/com/cleanapp/PendingShareStore.kt - Retry worker:
android/app/src/main/java/com/cleanapp/PendingShareWorker.kt
Manifest support is configured for:
ACTION_SEND+text/plainACTION_SEND+image/*ACTION_SEND_MULTIPLE+image/*
Retries are scheduled with WorkManager.
- Share a URL from Safari into CleanApp.
- Confirm the Share Extension appears as a share target.
- Confirm no editable compose screen appears.
- Confirm a digital report is created automatically.
- Share a post/link from X into CleanApp and confirm automatic submission.
- Share a screenshot into CleanApp and confirm an image-only digital report is created.
- Share multiple screenshots into CleanApp and confirm they are submitted together, up to 6 images.
- Disable network, share a URL/image set, and confirm the share completes cleanly without blocking UI.
- Reopen CleanApp and confirm the pending draft is retried automatically.
- Share text/plain into CleanApp from Chrome/X/Reddit.
- Confirm CleanApp appears in the Android Sharesheet.
- Confirm no compose screen appears.
- Confirm the report is submitted automatically.
- Share a single image into CleanApp and confirm image-only digital report creation.
- Share multiple images into CleanApp and confirm they are submitted together, up to 6 images.
- Disable network, share a URL/image set, and confirm the draft is queued.
- Reopen CleanApp or wait for WorkManager retry and confirm the draft is submitted later.
- The backend endpoint
/api/v3/reports/digital-sharemust be deployed and reachable from mobile clients. - The iOS App Group
group.io.cleanapp.sharedmust be provisioned in Apple Developer for both app IDs. - iOS Share Extension runtime behavior still needs final device/TestFlight validation because simulator/workspace builds are heavy and extension behavior is best verified on-device.
- Android share flow is implemented and
:app:assembleDebugsucceeds locally. - Video share, editing UI, and category selection are intentionally out of scope for this MVP.
- The backend preserves all shared images, but the legacy primary report image slot still uses the first image as the canonical inline image for downstream compatibility.
- Clean the previous Android build
yarn clean-android - Run Metro
- Open a new terminal window
- Run metro command
yarn run start
- Run the Android
yarn run android
- Remove the CleanApp application from the device if any was previously installed.
- Connect the device to the computer via USB.
- Do port reversing
adb reverse tcp:8081 tcp:8081 - Run Metro
- Open a new terminal window
- Run metro command
yarn run start
- Run the Android
yarn run android
Follow the react native guide: https://reactnative.dev/docs/signed-apk-android
- Update version numbers in
version.jsonand runnpm run sync-version - Use the interactive build script:
Or manually:
./scripts/build-android.sh release
yarn android:bundle && cd android && ./gradlew clean && ./gradlew assembleRelease && cd ../
- Install APK to the device
adb install android/app/build/outputs/apk/release/app-release.apk
- Update version numbers in
version.jsonand runnpm run sync-version - Build the AAB:
yarn android:bundle && cd android && ./gradlew clean && ./gradlew bundleRelease && cd ../
- The bundle release
android/app/build/outputs/bundle/release/app-release.aabis ready for upload to Play Store
The Android build script (scripts/build-android.sh) provides:
- Interactive Mode: Prompts user to choose build type
- Command Line Mode: Direct build execution with arguments
- Version Display: Shows current app version and build timing
- APK Information: Displays file locations and sizes
- Error Handling: Validates environment and dependencies
- Colored Output: Clear, professional build feedback
# Interactive build (recommended for first-time users)
./scripts/build-android.sh
# Quick debug build
./scripts/build-android.sh debug
# Production release build
./scripts/build-android.sh release
# Build both versions
./scripts/build-android.sh both
# Show help and usage
./scripts/build-android.sh --help