Cross-Platform Lifestyle App
Cross-platform travel and booking app with offline maps and editorial content
Cross-Platform Lifestyle App
A cross-platform travel and booking app built with Flutter for iOS and Android. Features map integration, headless CMS for editorial content, Firebase analytics, and a BLoC-based architecture with staging and production build flavors.
iOS + Android
Platform
Flutter Engineer
Role
From Design to Both Stores
Architecture & State Management
Feature-first architecture where each feature owns its view, provider, and state files. We used BLoC for complex stateful flows and Riverpod StateNotifier for simpler screens. Retrofit code generation gives us type-safe API clients without writing boilerplate.
Maps & Location Features
Mapbox with custom markers, clustering, and location-based search. I added offline map caching via Hive for areas with poor connectivity. Thousands of points on the map, no frame drops.
CMS-Driven Content
The headless CMS for articles, guides, and rich text with embedded media. I built a rendering pipeline that transforms the CMS rich text node tree into Flutter widgets with proper styling and image optimization. Harder than it sounds.
Multi-Flavor Deployment
Staging and production build flavors with separate bundle IDs, API endpoints, and Firebase projects. Codemagic runs CI/CD: PRs trigger test builds, merges to main deploy staging, tagged releases go to production stores.
Explore Without Friction
Interactive Maps with Offline Support
Mapbox renders location data with custom-styled markers that cluster at zoom levels. Search, filter, navigate to points of interest. When connectivity drops, previously viewed map tiles and location data are still available from Hive local storage. The app degrades gracefully instead of showing empty screens.
CMS-Powered Editorial Content
Content editors manage articles and guides in a headless CMS without ever talking to a developer. The app fetches structured content via the CMS API and renders it through a custom widget tree handling rich text, embedded images, videos, and cross-references between articles.
Feature-First Architecture
Each feature is a self-contained directory with its own view, state, and provider files. go_router gives us declarative, deep-linkable routing. New features are additive. They never require modifying existing feature code.
Under the Hood
Key Technical Decisions
BLoC + Riverpod Hybrid
The team initially wanted to pick one. We didn't. BLoC for complex multi-step flows (onboarding, checkout), Riverpod StateNotifier for simpler read-heavy screens (content lists, settings). Boilerplate stays proportional to complexity instead of being one-size-fits-all.
Headless CMS Rich Text to Flutter Widgets
The headless CMS delivers rich text as a nested node tree, not HTML. We built a recursive renderer that maps each node type to a Flutter widget. Headings, paragraphs, embedded assets, hyperlinks. Unknown node types fall back to plain text instead of crashing. The edge cases (nested lists inside blockquotes, images with captions) are where all the time went.
Dynamic Config Generation
Build-time code generation creates environment-specific configuration classes. Staging and production flavors get different API URLs, feature flags, and analytics keys. No runtime checks, no if-else per environment. Runs as a pre-build step in Codemagic.
What I Learned
Pick both and stop arguing
The BLoC vs. Riverpod debate ate two days. Using both reduced boilerplate by about 30% compared to forcing BLoC everywhere. Match the tool to the problem, not the other way around.
We estimated the CMS renderer at one week
It took two and a half. The headless CMS rich text format is well-structured, but edge cases multiply fast. Nested lists inside blockquotes, images with captions, inline code spans. Building it as a recursive widget tree (not string parsing) was the right call, but the scope was humbling.
We added build flavors in month three. That was a mistake
Spent a week untangling hardcoded environment references that would have been trivial config on day one. Set up staging/production flavors before writing your first feature.
Trusted Infrastructure Platform
Decentralized identity platform with custom auth, iOS client, and admin dashboard