DEV Community

mavoryl
mavoryl

Posted on

I scanned 10 mobile codebases for health issues — here's what I found

Every mobile repo I worked on had similar problems: very large PNG images, unused asset files that nobody removed, secret files added to git years ago, gradle files that changed from default settings. So I made a small CLI that scans a mobile repo and gives it a 0–100 health score in four areas (size, speed, stability, hygiene) with 50 checks.

To test the rules on real projects, I ran it on ten codebases I had on my laptop. Seven are well-known open-source projects. Three are from my own work and stay anonymous below — I will only describe them by stack ("a Flutter app", "an Android app").

npx mobile-repo-doctor scan ./your-repo
Enter fullscreen mode Exit fullscreen mode

Everything runs locally. Your code, file paths, and scan results never leave your machine. No account, no login, no telemetry. The CLI is one npm package. If you don't trust me, the npm bundle is a single file you can read.

The dataset

Public (7): AppFlowy, wikipedia-ios, compose-multiplatform, iCarousel, mundraub-android, golden_matrix, auto-dev.

Private (3, anonymous): two Flutter apps, one Android app.

By stack: 3 Flutter, 2 Android, 2 iOS, 2 KMP, 1 multi-stack (AppFlowy).

What the numbers said

The middle score across the ten repos was 95/100. This surprised me — I expected lower scores. But two repos scored below 60. The worst was 52.

Median Worst
Overall score 95 52
Size 91 4
Speed 96 83
Stability 100 71
Hygiene 93 33

Total findings across all ten repos: 327. Most are Info (148) — these are summaries like "here are your top size contributors", not real problems. The rest: 3 Critical, 17 High, 90 Medium, 69 Low.

I expected stability to be the worst area — security flags, low SDK targets, manifest problems. It was not. People now know these rules well. I saw almost no usesCleartextTraffic="true", almost no NSAllowsArbitraryLoads, almost nobody using a very old API level. The areas where modern repos get lower scores are size and hygiene — boring things nobody checks in CI.

The most common findings were not security issues

The top of the list, sorted by how many of the ten repos had each finding:

Finding Repos affected
Top size contributors (info) 10/10
Module/package inventory (info) 9/10
Duplicate asset files 8/10
WebP candidates (PNGs that should be WebP) 8/10
Oversized images 7/10
Unoptimized PNGs 7/10
Sensitive files in repo 6/10

Eight of ten repos have PNG assets large enough to benefit from WebP. This is a simple fix — one cwebp -q 80 command and you save real size. compose-multiplatform alone has about 7 MB of PNGs that could be WebP. AppFlowy has another 2.4 MB. One of the private Flutter apps has more than 10 MB. None of these are bugs. Nobody just did it yet.

The same with duplicate assets between sub-packages. Half of the multi-package repos had the same logo, icon, or splash image copied across four to six modules. wikipedia-ios has about 3.4 MB of duplicates. Nobody runs find on these files.

The "secrets" finding needs more explanation

Six of ten repos had a sensitive-file finding. But I want to be honest about what this means. Most are Tier-2 hits: google-services.json, GoogleService-Info.plist, debug.keystore. These files are usually safe to commit (Firebase configs are project-scoped, debug keystores are not release credentials). The check marks them as Low/ReviewNeeded for a reason — they need a careful decision, not an automatic reaction.

The honest number: two of ten repos (20%) had Critical-level sensitive files.env files in tooling subdirectories of two open-source projects. One has been there for years.

I also found one wrong finding: a _pub.pem file marked as sensitive because it ends in .pem. It is a public key — safe to commit. Fix coming soon.

A few things that surprised me

The number of findings does not show health well. The repo with the most findings (69) was iCarousel — an old, well-maintained iOS library. Almost all of its findings are info-level summaries, not problems. It scored 97/A. Meanwhile a Flutter repo with 61 findings scored 58/C. The mix of severities matters more than the count.

Even AppFlowy has image problems. AppFlowy is a popular OSS project with many contributors. They have ~7 MB of oversized images, 6 MB of unoptimized PNGs, 2.4 MB of WebP candidates. Nobody is bad here — this is what happens to an old project when no one takes care of asset hygiene.

KMP repos look good. auto-dev and compose-multiplatform scored 97 and 78. Only 2 repos so I cannot make strong conclusions, but the KMP ecosystem is young and the asset pipelines are usually clean. I need more samples.

The biggest concrete wins were boring

If I had to give each public repo one one-day task:

  • AppFlowy: compress those cover images — ~7 MB of oversized PNGs.
  • wikipedia-ios: remove duplicate assets across packages — ~3.4 MB of duplicates plus ~12 MB of unoptimized PNGs.
  • compose-multiplatform: oversized images add up to ~26 MB. Some are documentation samples, but worth checking.
  • iCarousel: really fine. Nothing to do here.

For the private apps: the Android one was clean (97/A, 12 findings). The two Flutter apps split — one was almost perfect (94/A), the other had ~80 MB of total reducible size across oversized + unoptimized + duplicate images. That is not a typo. It is also the one that scored 58/C.

What else it checks

This post focused on what showed up most in this scan, but the rule set covers more:

  • Android: low targetSdk/minSdk, debuggable release builds, missing ProGuard rules, missing minification, dependency hygiene (dynamic versions, SNAPSHOT deps, legacy support libs, mixed kapt/ksp), missing ABI splits, APK instead of AAB, native libs forced to extract on install.
  • Flutter: unused assets in pubspec, missing assets that are in pubspec, heavy dependencies (Lottie/SVG runtime weight), dependency_overrides in production, vendored packages, oversized SVGs, missing split-debug-info, large workspaces with too many local packages.
  • iOS: arbitrary network loads in Info.plist, hardcoded user paths in pbxproj, unversioned pods, low deploy target, too many disabled SwiftLint rules, bitcode enabled (deprecated), oversized resources outside sticker packs.
  • Cross-platform / hygiene: missing lockfiles (gradle wrapper, podfile.lock, pubspec.lock), deeply nested directory trees, large generated files committed by accident, sensitive files (with the Tier-1/Tier-2 split above).

71 checks total across all stacks.

Try it on your own repo

npx mobile-repo-doctor scan .
Enter fullscreen mode Exit fullscreen mode

Or as a GitHub Action (Marketplace listing):

- uses: Mavoryl/mobile-repo-doctor-action@v1
  with:
    scan-path: '.'
Enter fullscreen mode Exit fullscreen mode

You get HTML + JSON output, a health score, top issues, quick wins, and file paths for each finding. 50 checks for Android / Flutter / iOS / KMP / cross-platform. Runs locally, no telemetry, no account.

Caveats

Ten repos is a small sample. Per-stack medians (especially KMP at n=2) are noisy — treat them as informal. The dataset is mostly already-maintained projects, so scores are higher than a random sample would be. And the _pub.pem wrong finding is a reminder: even rules that are 95% correct need a way to suppress them, which is on the roadmap.

npm: https://www.npmjs.com/package/mobile-repo-doctor
GitHub Marketplace: https://github.com/marketplace/actions/mobile-repo-doctor

If you run it on your own repo, I would love to hear what you found — both real findings and wrong findings. The wrong ones are how the rules get better.

Top comments (0)