Runarchy Running Club App: Live Map, SOS, Badges

Image prepared by Author
This is the story of how I built a running club app for Runarchy, a run club in Istanbul with 12,000 followers on Instagram. One developer, five months, mostly after midnight. The app is now on the App Store and Google Play under the name Runarchy Running Club: a live map that shows your friends running, the club run of the week with pace groups, badges, an SOS button, a race calendar for all of Turkey and a club chat with AI moderation.
If you're thinking about building a running club app for your own group, or you just want to know what breaks when 300 runners start using one, this post is for you. But first, the short version of how I got here.
November 20, 2018, Şişhane. A colleague kept asking me to come running, so I finally showed up. Apart from him, I don't know anyone there. Captain Yasin, who I meet that evening and shamelessly ask for a winged Runarchy pin for my bag, will be my wedding witness years later.
In 2019, Yasin and I tried to build a running group mobile app together. We designed a few screens. Back then I was only an Android developer. With a server, a database, user login and password reset to build, we needed one more person. We couldn't find that person, and the project stopped. But the Tuesday runs, the Thursday track sessions and the Sunday Shift runs on Sunday mornings went on. The club's Instagram account reached 12,000 followers.
After I finished mixletics.com and devdiscipline.com, the sci-fi blog you're reading right now, that unfinished app came back to my mind. While working with AI, I had seen that I could now build the parts we were missing in 2019 on my own. “Why don't I build Runarchy's mobile app?” I thought. And there was the promise I had made to Yasin years ago.
In May 2026, I started working on the running club app again, this time in React Native, with Antigravity and Gemini. Supabase gave me the database, the login system and file storage.
At the start, this is what I wanted: The post for the run of the week goes up, people mark that they're joining and pick a pace group. When the run begins, recording begins too, and we can see the distance, the time and the Runarchy routes. After that, the run stays on our profile, and its distance is added to the kilometers on our shoes. And Yasin doesn't have to message me every time he needs to manage any of this.
Claude helped me with plans and analysis. I also spent many hours with GPT-6 Astra: We prepared the documents for KVKK (Turkey's personal data protection law) and for health data, ran security reviews and looked at feature ideas. Sometimes we talked about how to build a feature, and sometimes about whether we should build it at all.
I have a day job, so I worked on Runarchy at night. Later I checked: 43 percent of my commits in five months were made between midnight and 6 a.m. The busiest hour was 1 a.m. If you read my post about publishing an iOS app, you already know my working habits, so this hour won't surprise you. On days when I had a workout the next morning, I made do with four or five hours of sleep. I tried to catch up on the missing sleep at lunch breaks or on weekends. When I said “let me just finish this one thing” at night, I wasn't really asking my next-morning self.
Working with AI needs its own discipline. Over time, the project's rules file got too big. It was full of copies of the database schema, pieces of code and old decisions, and it grew past 40 KB. That's a bit much for a Markdown file, friends. Every session started by reading this file, so I was starting every task with an old encyclopedia. In October I cleaned it up and brought it down to 9 KB. Now the file only holds rules: The correct schema lives in the migration files, and the correct theme lives in the theme file. Around the same time, I also removed the explanation comments from the code in 130 files. If the code doesn't explain itself, what's missing isn't a comment. It's a better function name.
I also looked at my own session logs. In 5 weeks, I had run type checks by hand more than 1,000 times, and I had checked the version number more than 200 times. If you do the same thing a thousand times, it's time to turn it into a single command. So I wrote a one-command pre-release check: Are there type errors? Is there a forgotten console.log? Do the Turkish and English translation keys match one to one? Is the version number the same in all three files? Is any native package missing? If anything is red, the release doesn't go out. On my first TestFlight try, the build crashed on a black screen. The reason was exactly the last item on this list.
Over time, more features came in: seeing Runarchy members running on the map, getting a warning when you leave the route, sharing your run photo with Be OWL! (it puts your stats, your route and the club's owls on top of the photo), and sending an SOS with your location when you need help.

The run of the week, and Be OWL! putting your stats and route on top of a run photo.
SOS has a side effect in a running club app: It makes every member's phone ring, even when it's on silent. I write everything at night, but I can't test SOS at night.
Someone in the Runarchy test group asked:
“What happens if we press SOS?” A friend replied:
“You just call the normal way.” Another one added:
“Why don't we call from inside the app?” And I said:
“Slow down, guys, I'm just one person.”
The people in the test group are my fellow Runarchians, the friends I run with every week. I personally know the people whose distance was calculated wrong or whose run was cut in half; we'll see each other again on Tuesday evening. Fixing a bug and shipping a new version is one part of the job. Explaining to your friend why their run disappeared is the other part.
The bottom bar was a whole other problem. A running club app with seven buttons: Runs, Club, Races, RUN in the middle, Routes, Be OWL!, Profile. We knew seven was too many, but we couldn't give up any of them. We just couldn't let go, honestly, I swear. Then we learned that some members with tired eyes had made the text bigger in their phone settings. In the screenshot they sent us, the labels on the bar were sitting on top of each other. The fix was to redraw the bar around the RUN button in the middle and to stop the app's text size from growing past a certain limit. All seven buttons are still there. Now you can read them.

The seven-button bottom bar on the Route Detail and Runs screens.
At the same time, a running club app has to keep working as the club grows. In the first notification system, when Yasin posted a run, the app created a separate record for every member. With 300 members, I was saving the same announcement 300 times. I changed it to a single record and only kept track of the last notification each member had seen. The number on the bell icon could simply update when you came back to the screen, because the news about the run already came as a phone notification. I also made photos smaller on the phone before uploading them.
The same habit spread to other places. On the live map, every runner writes their own location as one row every five seconds and reads everyone else's location with one query. Whether a hundred people run or a thousand, the number of queries per person stays the same. The load grows at the same speed as the club, not many times faster. I also took the emoji reactions on run announcements out of the live updates. Preparing those live updates turned out to be the most expensive job for the database, and nobody notices if a reaction shows up one second late.
GPS tracks from old runs are archived with a 200 MB budget. When the budget is full, the oldest tracks are removed from the map, but the distance and time stay. In case Supabase's free plan isn't enough one day, I also wrote down the steps for moving everything to my own server, with all the traps along the way. I hope I never have to open that file.
See You at Kilometer Eight
The best part of building a running club app is that you have to run to test it. That's also the worst part.
My own phone is a Xiaomi Redmi Note 9S, a model from 2020. I comfort myself by saying, “If the app works on this phone today, it will work on any phone.”
After eight or ten kilometers, the app was shutting down. Location permission was on and battery saver was off, but Xiaomi's MIUI software still killed the app in the background at some point. You take your phone out of your pocket, and the recording is gone. The forty minutes you just ran are in your legs, but not on the screen.
The first time this happened to me was in Beşiktaş. I still had eight kilometers to go to get home, and I ran all eight of them complaining to my own app.
Changing a setting on the phone takes five seconds. Finding out if that setting works can take eight kilometers.
Adding the app as an exception in the phone settings can help, but I couldn't expect everyone to find those menus. I did everything I could to stop the app from closing. Then I accepted that it might still close, and tried to protect the run anyway. Now the app saves the recording to the phone every eight seconds. If you open it again within ten minutes, you can continue. If you open it later, it offers to find and save your unfinished run, for up to twelve hours.
Sadly, the distance you run while the app is closed isn't part of that recording.
We Ran 6.16 km, the App Said 12.27
In early October, we set up a test group with the Android users in our Runarchy running group, so we could see how the running club app behaved on different Android phones. For a few of our friends, the app recorded about twice the real distance. If only running were really that easy.
Android was sending the locations it had saved in the background again. And the app was counting points it had already processed one more time. When you count the same road twice, the kilometers go up, the pace looks great, and badges nobody earned start arriving.
I looked at the time of each location and removed the repeated ones. Then I fixed the wrong distances, took back the badges from those runs, and explained to our friends what had happened. Giving someone six extra kilometers and then taking them back, it turns out, is the social side of building a running club app.
GPS jumping around between buildings can also make a run look longer than it really is. To fix that, I added checks that filter out low-accuracy readings, small location wobbles and jumps that look impossibly fast.
There was also a time when nobody earned any badges. People came on Tuesday evening, ran and went home, but nobody started a recording, so for the app there was no run. For a while, I counted pressing the “Join” button as enough. But then planning to come and actually running were counted as the same thing.
After reworking the system three times, I set the rule for the launch: You earn badges only from runs recorded live in the app and not changed later. You can add distance by hand, but it doesn't count for badges. Deciding which behavior a small icon on your profile should reward took longer than putting that icon on the screen.
Back in 2018, I was the one who shamelessly asked the Captain for a pin. Two more Runarchy pins came later; both fell off and got lost. That first pin is still on my bag, can you believe it? Now, years later, I'm writing the rules for which run earns which badge in our mobile app. One of the badges is Night Owl. I'd be lying if I said I wasn't thinking of myself when I added it.

Badges on the Runarchy profile screen and the club's weekly leaderboard.
Where Did Yarış Radarı Come From?
In July, I wanted to grow the Races tab of the running club app: a calendar that brings together races in Turkey, which you can browse even if you're not a Runarchy club member.

The Races tab (a calendar of races in Turkey) and the Routes tab.
From the very beginning, a crawler was collecting race data. I worked on it during the whole project, and I kept improving how it collected information from different websites, removed duplicates and kept the calendar up to date.
When I needed race data for Mixletics too, I thought, “Why don't I turn this crawler into a separate product with its own website and data service?” As I explained in detail in this post, that's how Yarış Radarı (“Race Radar” in Turkish) was born.
Two weeks later, I removed the crawler from Runarchy and connected the app to this service. If I see wrong information in Runarchy's calendar, I fix it in Yarış Radarı. This way, I don't have to keep the same data up to date in two places.
After the calendar, I moved on to race results. In mid-October, I went through the results pages of 169 races, and 117 of them had results. The real problem was finding which timing company had the results for each race, and on which page.
That night I changed the design twice. At 11:52 p.m., I wrote a job that ran every ten minutes and checked the results of all races on its own. At 1:36 a.m., I deleted it. In between, I had realized something: Searching every ten minutes for results that nobody would look at was tiring out the timing companies' servers and using up my quota. Results would only be searched when someone asked for them. The race status is kept in a shared cache for fifteen minutes, so even if a hundred people look at the same race at the same time, only one request goes to the server. No scheduler, no polling for each person.
After a race, people don't remember their bib numbers. I don't either. If you first have to find your bib number in old photos to see your result, the most annoying part of the job is left to the user.
So I added search by first and last name. The app finds matching people, shows up to five options and asks, “Is this you?” Results are loaded when you open the screen or when you ask for them. Once a result is final, we don't keep searching for it again and again.
Some timing companies block requests coming from servers, but not requests coming from phones. For races like that, the phone reads the results page itself, saves the result only to that person's record and doesn't share it with anyone.
And a public API endpoint of the athletics federation was returning people's ID numbers and birth dates. I called the Turkish Athletics Federation right away, and together we closed this serious data leak.
The idea for the My Race Calendar screen came from a friend in the group. Your races are lined up on a timeline: Your next race waits under a start arch with a countdown. Races you've already run line up as bib cards with safety pins and tear-off lines. A cancelled race has a red CANCELLED stamp on it. This became my favorite screen in the app, and the idea wasn't even mine.

The My Race Calendar screen and the detail of the Istanbul Marathon we just ran: the club's fastest finishers and the participants.
Why “I Run Often” Almost Got Blocked
I added a word filter and AI moderation to the club chat.

The live run screen: club chat on top of the map; on the right, a live run in race mode.
“I killed myself today, great pace.”
In Turkish, this is a normal thing to say after a hard run. But the model I tested gave this sentence a score of 0.77 in the self-harm category. Instead of using the model's overall decision as it was, I looked at each category separately. I set a limit for violence, and I didn't use the self-harm score alone to reject a message.
To catch swear words with slightly changed spelling, you need to treat some letters as the same. But if you also treat “ı” and “i” as the same letter, the Turkish phrase “sık sık koşuyorum” (“I run often”) can get caught by the filter, because “sık” written with an “i” becomes a swear word. In a running club app, I decided it was more important for people to be able to say that.
Getting Runarchy Ready for Launch
While preparing the running club app for the stores, I went over many things, from the location permission texts to account deletion.
Some things in the running club app had to wait. There's no Strava or Garmin connection yet. HealthKit and Health Connect are on the list for later.
The App Store approved Runarchy 1.0.0 on the first submission. On Google Play, because I applied with a personal account, I needed twelve testers in a closed test for fourteen days. So this time, instead of a run announcement, I sent my club friends a test link.
For the store screenshots, I had turned on a demo mode that freezes the phone's clock. I forgot to turn it off, and for a while the clock was stuck at 8:16. A frozen clock on the phone of someone who builds a running app is a bit too much, even as irony.
What Five Months of Building Runarchy's Running Club App Taught Me
Hiding a button is user experience, not security. The button to Yasin's admin panel is only visible to him, but the real protection is the row-level permissions in the database. Everyone can read, only the admin can write. Even if you somehow find the button, you can't do anything with it.
Calculate the cost of a feature for all members, not for one person. Writing a separate notification record for every member isn't noticeable with 300 people, but with 3,000 it eats your whole budget. Code written for 300 people gets rewritten when the club grows, so writing it right the first time is cheaper. As one of my professors at university used to say: "With smarter software, you can cut the hardware cost a lot."
Everything in a running club app works in the simulator. Badges that never trigger, distances that double, results that can't be found, an app that shuts down at kilometer eight… The simulator showed me none of these. All of them came up on real runs, on real phones, with real people.
If you're building a running club app, you're going to run.
While I was writing this post, we were waiting for the team's promo video for the launch. I also wrote about the changes I made while preparing for the App Store in a separate post. And three months from now, I want to look at how many people use the app regularly, how many of the people who tap “Join” actually start a recording, and which features they use.
As for my Redmi, it's still on duty.
See you Tuesday evening.
Frequently Asked Questions
▸What features does a running club app need?
Start with the weekly club run: members say they're joining, pick a pace group, and record the run with distance, time and route. Runarchy then added a live map of friends running, route warnings, badges, an SOS button with location, a race calendar with results, and a club chat with AI moderation.
▸Can one developer build a running club app?
Yes. Runarchy Running Club was built by one developer in five months, mostly at night next to a day job. AI tools (Claude, Gemini, GPT-6 Astra) helped with planning, documents and server-side code, and Supabase removed the need for a separate backend developer.
▸What tech stack is the Runarchy running club app built with?
The app is written in React Native and runs on Supabase, which provides the PostgreSQL database, login, file storage and realtime updates. Race data comes from Yarış Radarı, a separate race calendar service that started as the app's own crawler. Everything stays inside Supabase's free tier.
▸Why did the running club app record double the distance?
Android re-sent locations it had collected in the background, and the app counted points it had already processed. The fix was to drop repeated locations by timestamp, filter out low-accuracy readings, small wobbles and impossibly fast jumps, and take back the badges earned from the wrong runs.
▸How does a running club app stay cheap as the club grows?
Calculate every feature's cost for all members, not for one. Runarchy keeps one record per announcement instead of one per member, writes one location row per runner every five seconds, archives old GPS tracks within a 200 MB budget, and took emoji reactions out of realtime updates.
▸Can other running clubs get an app like Runarchy?
Runarchy was built for one Istanbul club, but the same approach (React Native, Supabase, one developer, free tier) works for any running club or running group. If your club wants an app like this, reach out through the About page on this site and let's talk.


