Samuel . E . Zih
All projects
Maps

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

Inside the app

See what's happening around you.
Join an activity in one tap.
Chat to confirm the details.
Verified profiles.