Designed in Figma. Built from scratch in Xcode. Architected for scale.
## Overview
Ticketflow is an iOS application that connects event organisers and ticket buyers in one seamless experience. Organisers create and manage events, track attendance, and verify tickets on the door. Buyers discover events near them, purchase tickets, and access QR codes instantly from their phones.
Built specifically for the East African market β with UGX pricing, local venue context, and MTN Mobile Money / Airtel Money payment support planned for v2.
Event ticketing in Uganda is fragmented. Organisers manage guest lists manually, buyers pay via mobile money with no digital record, and ticket verification at the door is slow and error-prone. Ticketflow solves all three.
Solo designer and developer. Responsible for the full product research, architecture, UI/UX design, and SwiftUI implementation.
Started by mapping the East African events landscape identifying that the real gap wasn't just ticketing but the connection between discovery, purchase, and venue check-in in a single native experience.
Identified two core user roles with fundamentally different needs:
- Agent (Event Organiser) needs dashboard, event creation, attendee management, QR scanning
- Buyer β needs discovery, location-aware search, frictionless checkout, offline QR ticket access
Designed 13+ screens across both roles before writing a line of Swift. Key design decisions:
- Color palette β Black
#111111base, Pink#D4537Efor primary actions, Teal#5DCAA5for secondary accents. High contrast, event-poster energy. - Full-bleed event posters β Buyers need visual pull on the discovery screen. Poster-style cards create that without sacrificing information density.
- Role-separated flows β Agent and Buyer see entirely different home screens post-login. No role confusion.
- Frosted glass tab bar β Custom floating tab bar with gradient fade, matching modern iOS aesthetics without using the default
TabView.
Built on MVVM (Model-View-ViewModel) with a parent AppViewModel coordinating shared state across the app.
Models β UserModel, EventModel, TicketModel, PaymentModel
ViewModels β AuthViewModel, AppViewModel, EventViewModel, PaymentViewModel
Views β 13+ screens across Agent, Buyer, and Shared flows
Single source of truth via AppViewModel
Instead of having ViewModels talk to each other directly (tight coupling), all shared state events, tickets, payments, location, user role lives in AppViewModel. Child ViewModels are focused action handlers. When the backend arrives, only AppViewModel needs updating.
State-driven navigation via @Published
Every screen transition is driven by a published flag, not imperative navigation calls:
hasCompletedOnboarding β isAuthenticated β locationSetupDone β notificationSetupDoneEach flag flips, the UI reacts. No navigation stack hacks.
Local-first with clear migration path
All data is stored locally for v1 UserDefaults for session, FileManager documents directory for agent-uploaded event banners, in memory arrays for events and tickets. Every storage point is isolated in AppViewModel, so swapping in API calls later requires changing one file, not ten.
Dual image loading
EventImageView tries the file system first (agent-uploaded images), then falls back to the asset catalogue (sample/test images). Agents pick banners from their photo library via PhotosPicker images are saved to the documents directory and the file path stored in EventModel.bannerImagePath.
| Layer | Technology |
|---|---|
| Language | Swift 5.9 |
| UI Framework | SwiftUI |
| Architecture | MVVM |
| State Management | @Published / ObservableObject |
| Location | CoreLocation |
| Notifications | UserNotifications |
| Image Picking | PhotosUI / PhotosPicker |
| Password Hashing | CryptoKit / SHA256 |
| Local Storage | FileManager / UserDefaults |
| Design Tool | Figma |
Launch
βββ SplashView (animated TF logomark)
βββ OnboardingView (welcome + role selection)
βββ BuyerAuthView (email β password β date of birth)
βββ LocationPermissionView (GPS or manual city picker)
βββ NotificationPermissionView
βββ BuyerHomeView (Discover tab)
β βββ BuyerEventDetailView (full-bleed poster + info)
βββ AgentDashboardView (events overview)
- Splash screen with animated logo sequence
- Onboarding welcome illustration + role selection
- Auth β step-by-step email β password β date of birth
- Location permission GPS or manual city/country picker (60+ locations)
- Notification preference selection
- Discover home full-bleed hero poster, filter chips, weekly events scroll
- Event detail full-bleed poster, event info, refund policy, floating CTA
- My Tickets QR code access (in progress)
- Checkout tier selection, quantity, MTN MoMo / Airtel Money (in progress)
- Agent dashboard event stats, ticket sales, revenue summary
- Create event form with banner image upload via PhotosPicker
- Event detail attendee list, ticket breakdown
- Edit event
- QR scanner verify tickets at the door (in progress)
- Profile / account settings
- Notifications
- Search & filter
- Backend API integration (Node.js / Supabase)
- MTN Mobile Money + Airtel Money payment processing
- Real-time ticket verification
- Spotify integration β personalised event recommendations based on listening history
- Push notifications for event updates
Design before you build. Having 13 screens fully designed in Figma before touching Xcode meant architectural decisions were made with full context not discovered mid-build.
State management is architecture. The decision to use @Published flags for navigation instead of programmatic NavigationPath manipulation made the entire flow easier to reason about, debug, and extend.
Local-first is a feature, not a compromise. Building offline-capable from day one means the app works in low-connectivity environments which matters in Kampala.
Type consistency saves hours. Every model ID is UUID. Every foreign key reference is UUID. One inconsistency (eventId: String instead of UUID) caused a cascade of compiler errors that took longer to debug than it would have taken to be consistent from the start.
Rose Visuals β UI/UX Designer & iOS Developer Based in Kampala, Uganda πΊπ¬
LinkedIn Β· Β· Figma Portfolio
Ticketflow is an independent portfolio project. Not affiliated with any existing ticketing platform.