MigoMap
A co-activity planner — and the moderation problem that came with it
2025 · Remote
In one paragraph
MigoMap is a map-first co-activity planner: create an event — a hike, a study group, go-karting on Saturday — and people nearby can see it and join. It grew past 1,000 active users, started being misused as a dating app, and got an AI pre-publication gate that stopped the drift without punishing anyone legitimate. Live on the App Store.
What it is
The product is built on a simple observation: people want to do things with other people, and the blocker is rarely interest — it's coordination. So the map is the primary interface. You see what is happening around you, in one tap you join, chat confirms the details, and profiles are verified so you know who you're meeting.
The interesting problem wasn't technical
Past roughly a thousand active users a pattern appeared in the event descriptions. People were posting personal ads dressed up as activities. The app was quietly turning into a dating app.
This is a product-integrity problem before it is an engineering one, and it has a nasty property: it is self-reinforcing. Users who came for hiking see the drift and leave; users who came for the drift stay and post more. The composition of the platform shifts under you while the top-line user count still looks healthy.
Several users messaged me directly to say the app had started to feel unsafe. That kind of message is a leading indicator, not feedback — for every person who writes in, many more simply leave. Trust is far easier to protect than to rebuild.
What I built
A pre-publication gate, not a takedown queue
Every event description is classified before it is ever visible. This is the whole design. A post-publication takedown system means harmful posts are seen first and removed second — the exposure has already happened, the user who saw it has already formed a view, and you're left issuing corrections. A pre-publication gate means bad posts never become visible to anyone.
A fine-tuned DistilBERT classifier
Trained on roughly 2,000 labelled examples I assembled myself from three sources: genuine activity posts from the platform, public personal-ad examples, and synthetic borderline cases written to cover deliberately ambiguous phrasing.
DistilBERT because it is fast enough to run synchronously in the posting flow without adding noticeable latency, and small enough to host without meaningful infrastructure cost. A frontier model would have been more accurate and completely unjustified for a binary classification over two sentences of short text — the latency and cost would have bought accuracy the task doesn't need.
A threshold tuned for precision over recall
The asymmetry here is the important judgement. Blocking a genuine hiking meetup is worse than letting a borderline post through to a human. A false positive punishes exactly the user you are trying to protect; a false negative costs a review.
Confidence | Action |
High | Blocked outright, never published |
Medium | Held for manual review |
Low | Published normally |
Thresholds were tested against a held-out validation set and chosen to keep false positives under 2% while still auto-blocking the clear violations.
An appeal mechanism that feeds the classifier
Users can contest a block, and every appeal produces a labelled example from a real edge case — precisely the cases the initial training set didn't cover. The classifier improves on live data with no manual curation effort, and the users most affected by a mistake are the ones supplying the correction.
Results
The week-over-week growth in personal-ad posts stopped, while the platform continued growing past 1,000 active users.
Zero legitimate events blocked in the first two weeks after launch.
Harmful posts never became visible — no reactive takedowns, no corrections after the fact.
Users who had raised the problem reported feeling more comfortable on the platform afterwards.
Why act early
The honest cost-benefit: acting early cost a few days of classifier work. Waiting would have cost user churn and a reputation association I could not undo. By the time this pattern is visibly a problem to anyone running a platform, the users who felt unsafe have already left and told other people why.
Identifying and acting on weak signals before they become crises is something I now think about explicitly when running a product, rather than treating moderation as something you bolt on after it hurts.
Stack
Flutter · Go · MongoDB · geospatial indexing · DistilBERT (fine-tuned) · push notifications