I just shipped BingeMark, a free Android app that tracks movies, TV shows and anime in one place. Here's the stack and two bugs that ate a weekend each.
The stack
- Frontend: React Native + Expo (SDK 54)
- Backend: Python + FastAPI
- Database: MongoDB Atlas
- Hosting: Render
- Data: TMDB API (titles, images), OMDb (IMDb ratings)
- Extras: Google Sign-In, Google Drive backup (drive.file scope), AdMob for ads
One app for movies, TV and anime
Most trackers pick one lane. I wanted all three. The trick was treating everything as TMDB-shaped data, so anime is just TV/movie entries under the hood. One data model and one UI handle all three instead of three separate flows.
Bug 1: AdMob broke my release build
Adding react-native-google-mobile-ads blew up the Gradle build with compileReleaseKotlin FAILED. The cause: the newer ads SDK was compiled with Kotlin 2.3, but Expo SDK 54 uses Kotlin 2.1, a metadata mismatch. Fix: pin the library to a version that ships an older play-services-ads compiled against Kotlin 2.1. Lesson: with Expo, your native deps have to match the Kotlin version Expo bundles.
Bug 2: a rewatch that wouldn't save
Logging a second rewatch threw a 500. It was a classic Python datetime trap: comparing a naive datetime (from Mongo) with an aware one (freshly created) inside a max(). Fix: a small helper that normalizes everything to UTC-aware before comparing.
Takeaways
- Match native dependency versions to your Expo/Kotlin version before you debug for hours.
- Always store and compare datetimes as timezone-aware.
- Keep one clean data model even when the content types look different. It saves you everywhere later.
It's live if you want to poke at it: https://play.google.com/store/apps/details?id=com.bingemark.app
Happy to answer anything about the stack in the comments.
Top comments (0)