The Journey
2019 – 2021
Software Engineer
Built foundational product features — trade-in, brand pages, product comparison. Adopted RxSwift and MVVM. Shipped Tokopedia's first Apple Watch app, featured on the Indonesian App Store.
2021 – 2023
Senior Engineer
Moved to Payment & Fintech. Owned the universal Thank You page, built Buy Now Pay Later end-to-end, and designed the layout-driven rendering pattern adopted across the codebase. Led the Objective-C → Swift AppDelegate migration.
2023 – 2024
Lead Engineer
Led a team of 4 engineers across Payment and Travel iOS. Drove the MVVM → TCA architecture migration. Conceived and shipped Tokopedia's e-Pharmacy — the most complex initiative of my tenure.
Flagship Projects
e-Pharmacy
Post-COVID, Tokopedia identified medicine sales as a major untapped market. I led the end-to-end iOS initiative — from business research and vendor licensing strategy through to the full purchase flow.
The core challenge: medicines require pharmacy vendor licensing, and many require a valid prescription. We built a catalog classifying every medicine as OTC or prescription-only, then wired up the entire compliance layer in-app.
What we built
- ▸ Medicine catalog with OTC vs. prescription classification
- ▸ In-cart prescription flag — prompts upload when required
- ▸ Backend OCR validation of prescription images
- ▸ Consultation module via HelloDoc (on-call doctor, free tier)
- ▸ Prescription-to-checkout bridge — validated script unlocks purchase
- ▸ Vendor licensing strategy via onboarded pharmacy partners
Buy Now, Pay Later
Tokopedia had always required upfront payment. BNPL introduced deferred payment — a first for the platform — and I owned the entire iOS implementation across every entry point.
The feature was driven by product value, not product type: given the item price, we surface available lenders, tenures, and charges side by side so the customer can compare and choose before adding to cart.
Implementation
- ▸ PDP widget — lender comparison, tenure options, charge breakdown
- ▸ Cart widget — selected BNPL option persisted through checkout
- ▸ Cart API extension — additional fields passed with BNPL selection
- ▸ Multi-provider support with sort by tenure or interest rate
Apple Watch Extension
I proposed the Apple Watch idea, designed the initial UX wireframes, and built the extension end-to-end. The watch app surfaces a user's wishlist items — product name, price, and a deep link back to the main app.
The feature was featured on the Indonesian App Store — a milestone for the team.
Technical challenge
The main app used a static network library to reduce compile time. Adding the Watch extension meant the static library was bundled twice — once in each target — causing significant binary size bloat.
The fix: convert the network module from static to dynamic library. Both targets then shared a single copy at runtime, eliminating the duplication and bringing bundle size back under control.
Universal Thank You Page & Layout-Driven Rendering
Every payment flow in Tokopedia — product purchase, seller wallet withdrawal, top-up, and deferred ATM payments — lands on the same terminal page. I rebuilt this as a single, signal-driven surface that adapts its layout entirely based on payment method.
Deferred transactions (common in Indonesian banking) show a live countdown and payment instructions. The rating engine and product recommendations were added as optional layout slots.
The layout-driven pattern
A single API returns layout definitions for a page. A second pass fetches component data only for visible layouts — keeping payloads small and enabling streaming. If a component fails, it is hidden silently. If a layout fails, a targeted retry fetches only that layout ID.
This pattern scaled beyond the Thank You page — it became the standard for brand pages, product recommendations, and every new server-driven surface we built after.
AppDelegate Decomposition & Swift Migration
Tokopedia's AppDelegate was a monolith that nobody wanted to touch. Universal links, deep linking, analytics, A/B experiments, push notifications — years of accumulated responsibility in a single file. One mistake would break the app at launch.
I led the migration in phases: extract each responsibility into its own manager class with mirrored lifecycle methods, then make AppDelegate a pure orchestrator. Final step: rewrite in Swift.
Safe rollout strategy
- ▸ Phase 1: Extract analytics, deep link router, A/B testing, push notifications into separate manager classes
- ▸ Unit tests asserting each lifecycle method is called exactly once
- ▸ New Swift AppDelegate shipped to beta group across 4 release cycles
- ▸ Production flipped only after beta validation — zero incidents
More Work
Device Trade-in
Built the complete device diagnostic pipeline — Bluetooth, Wi-Fi, SIM, display grid, camera — integrated from the PDP phone section to generate instant trade-in pricing.
Brand Category Pages
Samsung and Apple branded shopping experiences with hero banners, video, collapsible sections, and dynamic carousels — rendered incrementally via GraphQL layout-first API.
Product Comparison
Side-by-side product comparison surface launched from the PDP. Scrollable key-value grid with fixed column structure and dynamic row count per product category.
Seller Wallet (Saldo)
Rewrote the credit/debit card withdrawal modules for seller balance payouts. Built the T&C flow, bank minimum-amount validation, and multi-bank routing.
Travel Platform
As Lead, managed the hotel and flight booking iOS team. Drove the MVVM → TCA architecture migration across the travel vertical, modernising the codebase and improving test coverage.
React Native → Native
Migrated React Native screens to native iOS across multiple modules, improving performance and eliminating the cross-runtime overhead for high-traffic flows.
Architecture Evolution
The iOS architecture at Tokopedia evolved significantly over my five years — and I was involved at each transition.
MVVM + RxSwift + SnapKit
Initial architecture. Reactive bindings via RxSwift, programmatic layouts with SnapKit. Writing unit tests for Rx streams was non-trivial and slowed feature delivery.
MVVM + Texture (AsyncDisplayKit)
Frame rate drops and slow initial page loads on complex views triggered the move to Texture. UI kit initialisation moved to background threads; only layout commit ran on main. A significant performance win for feed and product surfaces.
TCA (Composable Architecture) + RxSwift
Point-Free's TCA uses Combine internally, but the platform team ported it to RxSwift to match the existing reactive foundation. The result was dramatically better testing ergonomics — less time writing tests, more time building features. Payment and Travel were migrated under my lead. 40% reduction in critical bugs.