Context
SmartView extracted and formatted publisher articles inside the SmartNews app. Millions of people used this core reading surface, and the existing pipeline had accumulated publisher-specific behavior over time. Replacing it in one switch would have made every parsing difference a release risk.
I led the iOS implementation of SmartView v2. The work had to improve the extraction code while preserving the existing renderer as a way back when a page or configuration did not behave as expected.
Parallel implementation
I built SmartHTMLExtractorV2 beside the first extractor instead of changing the old pipeline in place. The two implementations let us compare behavior and move traffic incrementally.
The new extractor lived in a Swift module named SmartHTML. I wrapped SwiftSoup behind an internal API rather than letting its types spread through the app. That boundary gave the extraction pipeline one place for HTML parsing and cleanup, and it kept a third-party parser from defining the rest of our rendering code.
The pipeline applied CSS rules delivered by backend services and converted the result into internal formatting models.
Rollout and fallback
Client conditions selected v1 or v2, so the two extractors could coexist during rollout. We could limit exposure while checking production content instead of moving all users to the new path at once.
I also added fallback behavior for failures in the client-condition configuration, including the stage and production URL choices used by the pipeline. Edition-aware proxy behavior kept the US and Japanese editions on their intended paths. Image selection accounted for iOS version as well, including JPEG and WebP support where appropriate.
Results
SmartView v2 shipped as a parallel rendering system with feature flags and fallback behavior. The team could validate the new extractor incrementally while the first implementation remained available. The rollout completed without regressions to the existing article-reading experience during the migration. The new Swift module also provided a smaller boundary for future parsing and formatting work inside a mixed Objective-C and Swift codebase.
What I'd do next
I would next define the evidence needed to retire v1, including representative publisher samples, edition coverage, configuration failures, and supported iOS versions. Once those checks passed, I would remove the old path and the branching that existed only for migration.