CAMDOM — Development Timeline
Day-by-day account of CAMDOM development from genesis (May 2024) through store approval and post-launch OTA updates. The complete story of building a BLE mesh consent protection app under extreme deadline pressure.
CAMDOM — Development Timeline
The complete story of how one developer built, stress-tested, broke, fixed, and shipped a cross-platform BLE mesh consent protection app in approximately 3 months of active development, followed by weeks of store review purgatory.
1. May 2024: Genesis
May 22: Project group "Camdom App" created by Felipe Almeida in WhatsApp. First message: encryption notice. This is the earliest timestamped artifact of the project.
The conceptual phase established the core architecture:
- BLE mesh communication between paired devices
- Cross-platform Android + iOS
- Privacy by design (no data collection, no servers)
- React Native + Expo as the framework
- Custom BLE module using Expo Modules API (JSI) for sub-millisecond native calls
The team at this stage was Felipe (product/management), Alefita (technical lead), Mikael (technical collaborator), and Victor (DevOps/App Store). Maso Heck participated separately as the Innocean Berlin designer.
2. Jun-Jul 2024: Core Development
June 6: Initial commit. Expo 51, React Native 0.74.2, React 18.2.0. The project scaffold was created using Expo's create-template.
June 16: Pipeline added — EAS Build, GitHub Actions v1. CI/CD established early.
July 1: Native Modules defined. Skia + Reanimated V3 added. The architecture decision to use Expo Modules API (JSI) instead of the Bridge was made here — critical for the sub-second BLE state machine that would become the app's core.
July 7-10: The BLE module was built from scratch.
BleManagerModule.kt(Kotlin) for AndroidBleManagerModule.swift(Swift) for iOS- TypeScript API surface in
modules/ble-manager/
By July 10, cross-platform BLE was verified: Android and iOS devices could scan, connect, and exchange packets.
July 22: Android scanning and peripheral management completed. Commit 68c2810: "Android Finally 100%". The BLE peripheral + central roles were both functional on Android.
July 29: V1.0.0 Android — Firebase, Google Auth, Apple Auth added. The authentication layer was built.
August 2: V2.0.0 — Peripheral manager feature branch merged. The GATT server/client architecture was established: one device acts as server (peripheral), others as clients (centrals). This is the fundamental BLE topology that CAMDOM uses.
At this point, the core technical stack was complete:
- Expo Modules API (JSI) custom BLE module
- GATT server/client protocol
- Cross-platform (Android + iOS)
- React Native with Reanimated for animations
- Skia for canvas rendering (the "ball" UI)
3. Aug 1-9: Pre-Crunch
August 1-9: Mikael supported the implementation with Figma materials and broader technical collaboration. Maso Heck supplied Photoshop/PSD design materials through Innocean Berlin. Version iterations accelerated. Client testing (Innocean Berlin / Billy Boy) began.
The layout was built from Figma exports, but as Alefita later noted: "o figma que ele fez, como só exportou um monte de png do Photoshop só serve mesmo como referencia visual" — the Figma was a collection of Photoshop PNGs, not a proper component-based Figma file, making pixel-perfect implementation impossible without manual measurement.
4. Aug 10-13: The iPhone Discovery
August 10, 19:44: Alefita's first message to Felipe after setting up the Mac M1 + iPhone:
"oiee, boa noite, terminei de configurar ambiente, iphone, porra toda agora" "to ha 1 dia com o iPhone neh, OMG, como a UX e diferente do android, agora eu entendi todas as estranhezas que vc sempre fala sobre o funcionamento do teclado nos projetos react native kkkkkkk"
This was the moment cross-platform testing became possible. The iOS experience was immediately different — keyboard behavior, scroll physics, the silent switch, NFC popup behavior, and the onboarding scroll were all "HORRIVEL, UM NOJO" compared to Android.
August 10, 19:51: Alefita discovered that Android-to-Android BLE was broken but had a simple fix: "descobri pq o android ta com pau ja tbm, tem a ver com o tamanho dos pacotes, mas e uma config boba hehe"
August 12, 02:15: Version 2.17.0 released — the first "real" version sent to clients. Menu 100% on all screen sizes, onboarding updated, end-to-end flow per Figma, Buy A Condom screen, Android/iOS connection fixes, reconnection improvements. Two items were still 80%: background alarm integration and multi-device disconnect consensus.
August 12, 06:26: Client feedback arrived immediately:
- NFC popup was interfering with UX
- Alert volume needed to be maxed out
- Multi-device UX needed discussion
- Simultaneous app exit caused issues
5. Aug 14-19: The Crunch
This was the most intense period of the project. Day-by-day:
August 14, 05:35-06:45: Felipe asked for a version. Alefita had been up all night. Version 2.18.0 was released at 06:45 — Android and iOS. Changes: volume fixes, onboarding permissions, background modes, DND removal, alarm cache fixes, NFC iOS disable attempt, layout adjustments, haptics, Android-iOS connection fix, alarm fix on swipe back.
August 14, 08:37: Felipe reported: "Android nao ta funcionando. Tentei conectar meu iOS com Android. Nao foi. Android ficou travado." The Android connection was broken. Felipe told Alefita to sleep: "Descansa um pouco. E vemos isso hj a tarde."
August 15, 05:40: Felipe had been dealing with his own work. The client was testing with 3 devices. Alefita revealed she had secretly deployed OpenReplay session replay: "Eu adicionei algo em segredo na versao de ontem. Temos session replay habilitado desde a ultima versao."
August 15, 09:05: The client reported Android-to-Android was completely broken: "nao funcionou a conexao entre 2 androids, mano. nada. nao funciona." Alefita was shocked — "Impossivel nao ta funcionando" — she had validated Android-to-Android extensively.
The root cause: a retry logic issue combined with Android Bluetooth bond state pollution from previous test versions. Users needed to clear Bluetooth pairings in system settings.
August 16, 00:33: Version with alarm fixes, multi-device disconnect corrections, Android-iOS server election logic fix. The key discovery: "a logica que eu adicionei pro retry, deve estar com problema no android" and the server election logic was causing Android devices to stop scanning when they saw an iPhone nearby.
August 16, 12:03: Client design call with the designer. Alefita negotiated: finish connection fixes first, then animations. Sebastian (client) agreed: don't touch layout anymore.
August 17, 09:57: Alefita reported identifying the Android-iOS issue and the "cache" problem: "nao so identifiquei o problema no Android X IOS como o que eles chamam de problema de cache." The "cache" bug was actually the app entering alarm state when the first packet after connection failed.
August 18, 10:28: Connection issues reportedly closed. Version 2.24.0 released. NFC research continued — Alefita found the com.apple.developer.passkit.pass-presentation-suppression entitlement but it required iOS 17.4+ and Apple Developer contact. Felipe decided: "So desabilita. Nao tenta usar. Vai dar ruim."
August 19, 01:27: Three animations still missing. Version generating. Alefita was simultaneously working on NFC disable, German translations, and animations.
August 19, 05:49: CRISIS. The app was crashing on iOS entry due to CoreNFC. Felipe: "O app nao funciona. Crash no ios. Mensagem do cliente." Felipe's instruction was clear: "Foca na conexao e na estabilidade. ESQUECE o resto."
Alefita identified the CoreNFC crash immediately and generated a fix build. By 08:03, Felipe confirmed it was working on both platforms.
August 19, 15:25-19:52: Multi-device with 3 iOS still had issues. Alefita worked on the migration logic — the fundamental problem was that when an Android joined iOS-only sessions, the server migration was visible and disruptive.
August 19, 19:52: Version 2.31.0 released — Android and iOS. "Amanha e o dia da 3.0.0 ein hehehe" (Tomorrow is the day of 3.0.0).
August 19, 22:16: Felipe reported iOS-Android still not connecting on his device. Bluetooth bond state issue again.
6. Aug 20-24: Stabilization
August 20, 05:41: The client reported iOS-iOS was working perfectly yesterday but broken today. Android hadn't received the 2.31 update. Felipe was worried: "To vendo seu esforco. Mas essas ondas e vindas tao ferrando a relacao com o cliente. Acabei de saber que perdemos um outro projeto com eles."
August 20, 08:39: Alefita had a breakthrough. The server election logic was solved with a device-ID-based approach: iOS devices get IDs 0-124, Android 126-250, the server always gets 251 (Android) or 125 (iOS). If an Android is present, iOS devices skip their first 10 scans to let the Android be found first. "EU SOU GENIAL CARA"
August 20, 18:39: Version 2.34.0 generated. The iOS-Android server election problem was solved at a fundamental level.
August 21, 05:33: Client feedback was dramatically positive: "IOS com IOS = LINDO. IOS com ANDROID = BONITO." The only remaining issue was Android-to-Android (which the client couldn't test) and some alarm configuration parity between platforms.
August 22, 06:16: Another crisis. The client tested with the wrong Android version and reported regression. Alefita: "mano n ta a mesma coisa, os caras sao cegos na moral que raiva" — they hadn't opened the Options menu where alarm settings lived, so features that were disabled by default appeared broken.
August 22, 07:04: Felipe at a breakfast with the Governor of RS. "Descansa. Vamos trabalhar de forma mais reta agora."
August 23, 05:51: Alefita had been sick (food poisoning from street food). "Acordei vomitando." Still working on the final version. Version 2.38.0 was the target "final" version.
August 25, 15:26: Version 2.38.0 confirmed working. Felipe confirmed: "Ja pode testar. E coisa no menu, ta pronto com tudo que combinamos."
7. Aug 25-Sep 1: Store Approval Push
August 27, 11:38: Client feedback arrived via PowerPoint. Felipe: "Vamos ter bastante cuidado em alterar qualquer coisa. Estamos muito proximos de fechar."
August 29, 07:56: Felipe asked for timeline: "1 - Quando teremos todos os bugs resolvidos? 2 - Quando trabalharemos no design e animacoes?" Felipe's strategy: "Fecha a versao e manda. Eles validam. Ai tu faz as animacoes. Entregas parciais."
August 30, 05:34: Alefita had been up all night. Felipe's concern: "Preciso me dizer Alef. Pra eu ir controlando o cliente. Ta muito em cima. Lancamento em 4 dias."
August 30, 09:04: Version 2.39.0 submitted. Google Play rejected for family policy compliance. Victor would fix the privacy page.
September 1, 18:58: Version 3.0.0 pushed to production on Android. Alefita explained the Expo Updates strategy: "assim que abrir o app, ele atualiza pra 3.3.1. Android e IOS." The force update system was now active — the app would check for updates on splash screen and install them automatically.
September 2, 04:28: Felipe: "A partir de agora so vamos fazer exatamente aquilo que eles pedirem ok? Ja investimos demais nessa app. Precisamos parar."
September 3, 06:02: The proximity alarm (distance-based) was disabled after testing showed it was unreliable. Felipe: "bora remover esse lance do DISTANCIAMENTO." Version 3.3.0 was the production version, 3.3.1 was the OTA update that disabled distance alarm.
8. Sep 2-20: The Apple Wait
September 4, 07:27: The After Effects animation files arrived from the designer. Alefita began replicating keyframes.
September 5, 02:11: Animation reproduction was painful: "Essas 2 animacoes sao um inferno de reproduzir e nao ficar travado." The After Effects project was too heavy to replicate exactly, so Alefita approximated.
September 5, 11:46: NEW CRASH. iOS was crashing in certain multi-device scenarios. Felipe: "nao tinha nada disso na versao que testamos hoje cedo." The issue was a leftover disconnect event handler conflicting with the new alarm behavior.
September 6, 06:34: Another crisis. Felipe: "nao ta funcionando segundo eles. Tao surtados." The client tested 3 iOS and it was failing. Felipe: "Conserta isso. essa e a real."
September 8, 09:11: Felipe had 3 iPhones and could record iOS videos. Alefita had 4 Androids. Division of labor for video evidence.
September 9, 11:24: Felipe confirmed 3 iOS was working. A leftover disconnect event handler was removed, fixing the issue.
September 10, 07:28: The final edge case: when 2 iOS connected first and an Android joined later, the migration was disruptive. Alefita: "Isso nao e novidade nao" — this behavior was agreed upon months ago.
September 11, 01:00-02:30: Late night testing session. Felipe's Android Bluetooth was malfunctioning (hardware issue, not software). The 3 iOS test passed. Videos were recorded and uploaded to Google Drive.
September 11, 08:41: "TUDO APROVADO... Agora e esperar a apple" — Android was approved on Google Play. Now waiting for Apple.
September 13, 06:53: Apple rejected again. The sign-out button crashed the app (it hadn't been tested because the client never intended to have sign-out). Alefita: "os caras tbm nao, pq na cabecinha deles n existia o signout. eu quem coloquei por obrigacao da apple."
September 13, 09:21: Felipe listed remaining items: keyboard UX on login, logo cut off on Android, German translation corrections, terms of usage text changes.
9. Post-Launch: OTA Updates
After the App Store finally approved (around mid-September), the remaining improvements were delivered via Expo Updates (OTA) without requiring store resubmission:
- Animation improvements (menu appearance, button fade-in, icon pulsing)
- Keyboard UX for login/signup screens
- Layout refinements across screen sizes
- Sensor proximity warning adjustments
- German translation corrections
- Text and color adjustments per Figma
10. Version Number Chronicle
| Version | Date | Platform | Key Changes | Issues Found |
|---|---|---|---|---|
| 2.17.0 | Aug 12, 02:15 | Both | Menu 100%, onboarding, Buy Condom, connection fixes, reconnection | Multi-device disconnect consensus, background alarm 80% |
| 2.18.0 | Aug 14, 06:45 | Both | Volume fixes, permissions, background modes, DND removal, alarm cache, haptics | Android connection broken after release |
| 2.19.0 | Aug 15 | Both | Android fixes, connection retry logic | Android-to-Android completely broken (bond state pollution) |
| 2.24.0 | Aug 18, 10:31 | Both | Connection improvements, NFC disable attempt | NFC Apple entitlement required |
| 2.31.0 | Aug 19, 19:52 | Both | CoreNFC crash fix, multi-device, migration logic | iOS-Android server election broken |
| 2.32.0 | Aug 20 | Both | Server election fix (device ID ranges), iOS scan skip for Android | "Cache" bug (false alarm on first packet failure) |
| 2.34.0 | Aug 20, 18:39 | Both | iOS-Android server election solved fundamentally | Client tested with wrong Android version |
| 2.35.0 | Aug 22, 00:37 | Both | Multi-device disconnect fixes, Android alarm parity | Intermittent iOS disconnect bug |
| 2.38.0 | Aug 25 | Both | German translations, layout fixes, all PPT items addressed | Candidate for "final" pre-store version |
| 2.39.0 | Aug 30, 09:04 | Both | Figma text/color adjustments, bug fixes, German corrections | Google Play family policy rejection |
| 3.0.0 | Sep 2, 14:51 | Both | Store submission version, animations (basic), force update system | Build number issue (3.0.0 < 2.42) |
| 3.3.0 | Sep 3 | Both | Production version on stores, proximity alarm disabled | iOS crashes with 3 devices |
| 3.3.1 | Sep 3 | Both | OTA: distance alarm disabled, menu adjustments | 3 iOS crash on alarm dismiss |
| 3.8.0 | Sep 5 | Both | Disconnect event handler cleanup, ping-pong keepalive | Client found alarm dismiss -> home navigation bug |
| 3.10.0 | Sep 6 | Both | Full test recording version, all scenarios validated | 3 iOS intermittent issues |
| 3.11.0 | Sep 8 | Both | Multi-device edge case fixes, force update enabled | 2 iOS + 1 Android late-join migration |
| 3.12.0-3.12.4 | Sep 8-9 | Both | Disconnect behavior fixes, UI state corrections | Leftover disconnect handler causing false errors |
| 3.13.0 | Sep 9 | Both | Final test version before Apple review | One edge case: server disconnect not propagating |
| 3.15.0 | Sep 10 | Both | Stability fixes, bluetooth state check before packet send | Felipe's Android hardware Bluetooth issue |
| 3.16.0-3.17.0 | Sep 10-11 | Both | Ping-pong timeout fix, disconnect state guard | Intermittent scan freeze on Android |
| 3.20.0 | Sep 11 | Both | Rolled back to 3.15 with version number only | Previous versions introduced regressions |
| 3.22.0 | Sep 13 | Both | Apple sign-out crash fix, keyboard UX, layout corrections | Apple rejected for missing sign-out |
| 3.23.0+ | Sep 13+ | Both | German corrections, text fixes, terms of usage | Final pre-launch polish |
11. Key Numbers
| Metric | Value |
|---|---|
| Active development period | ~3 months (Jun-Aug 2024) |
| Store review period | ~3 weeks (Sep 2024) |
| Total versions released | 30+ (2.17.0 through 3.23.0+) |
| Peak version velocity | 3-4 versions per day (Aug 14-19) |
| Devices tested simultaneously | Up to 5 (4 Android + 1 iOS via Mac M1) |
| Apple review rejections | 3+ (NFC, privacy policy, sign-out, education) |
| Google Play rejections | 1 (family policy) |
| All-nighters | 5+ documented |
| Final store version | 3.3.0 (Android approved Sep 1, iOS mid-Sep) |
This document captures the human reality of shipping software under deadline pressure. The version numbers tell one story; the WhatsApp messages tell another.