AfCircle started the way most “quick” projects do. Two founders DM’d me on a Friday with a Figma board and a firm deadline: go live before the next investor update. There was no mobile team—just me, the brief, and a shared Notion doc of feature ideas. I said yes, booked a Monday kickoff, and spent the weekend sketching the shape of the codebase.
Week Zero: Setting the Table
- Claimed the
afcircle
repo, dropped in my zero-to-one Flutter skeleton, and wrote a README that covered naming conventions and release steps. - Agreed on a three-track roadmap with the founders: core feed, community features, creator tools. Anything outside those lanes went to a parking lot.
- Wired GitHub Projects + Loom updates so the non-technical crew could follow along without waiting for daily standups.
What I Actually Shipped
- Feeds, reels, and disappearing stories. Reels needed buttery scroll, so I built a caching layer on top of
flutter_cache_manager
and tuned prefetch distance per device class. - Live spaces with admin controls. A GetX controller owns the room state while a Kotlin module handles audio focus, recording, and Bluetooth quirks.
- Chat with an AI wingman. The assistant drafts replies, but the UI stays responsive thanks to an isolate-backed queue that keeps inference off the main thread.
- Creator monetisation. Stripe Connect on the backend, slick payout dashboards in Flutter, and abuse-prevention hooks via a small Laravel service.
- Release confidence. Shorebird patches stitched into Codemagic so hotfixes arrive faster than app store reviews.
Architecture in Plain Words
I split the code by outcome: lib/feed
, lib/stories
, lib/spaces
, lib/profile
, lib/moderation
, and a shared common/
layer for design tokens, routers, and utilities. Each feature folder owns its models, widgets, services, and controllers. When we killed a prototype feature, I deleted one folder and watched the compiler yell about any forgotten dependency. Clean and fast.
State lives in GetX controllers. Authentication, session hydration, and story timers sit in dedicated managers. Every route declares its Binding
, so dependency injection is explicit and easy to test. When we needed to bridge into native land, I dropped into Kotlin/Swift files that mirror the folder structure to keep context switching painless.
Tooling That Saved Me
- CI from day one. GitHub + Codemagic run tests, build artifacts, prep Shorebird patches, and tag releases (
vX.Y.Z-patch-N
). - Instrumentation early. Firebase Analytics + Sentry were wired in week one. By week three we had stickiness dashboards that influenced backlog decisions.
- Research notes in Notion. After every release I sent founders a form that tied feedback to screenshots and logs. The loop kept scope sane.
- Experiment toggles. Product folks can flip beta features without waiting for a binary. It’s a simple Remote Config panel but it kept us nimble.
Numbers that Matter
- First TestFlight build: day 7.
- Shorebird-powered hotfixes: 14 in the first quarter.
- Daily active creators after launch: 1,000+.
- Manual moderation load: down 38% after the AI assistant dropped in.
What I’d Repeat (and Skip)
- Repeat: ruthless focus on the first release candidate, keeping design decisions close to the code, pairing with founders twice a week.
- Skip: relying on off-the-shelf media pickers. I eventually wrote Kotlin channel code to fix EXIF rotation issues anyway.
AfCircle reminded me why I love showing up as the “founding engineer.” When product, architecture, and release strategy move together, a single Flutter lead can ship something substantial. If that’s the energy you need for your team, let’s talk.