The Monolith Problem
When I rejoined TouchNote in 2010, the platform was a PHP monolith. The website was the application — server-rendered HTML, business logic mixed with view logic, and zero consideration for non-browser clients. This was fine when 100% of users were on desktop browsers.
But mobile was coming. TouchNote's product was inherently mobile — sending a postcard from your phone, triggered by a meaningful moment, delivered as a physical card. The mobile app was the product. The website needed to become secondary.
The Wrong Way to Add Mobile
The tempting shortcut was to add mobile-specific endpoints to the existing codebase. Tack on a /mobile/api/ directory, write some JSON responses, and call it an API. We briefly considered this. I argued against it.
The problem: your business logic ends up duplicated or shared in ways that create coupling. The mobile API becomes a second-class citizen. When you want to change the checkout flow, you have to change it in two places. When mobile has different requirements, they fight with web requirements in the same codebase.
The Right Architecture
What we built instead was a clean API layer that both the web frontend and the mobile apps consumed:
[iOS App] [Android App] [HP webOS App] [Website]
↘ ↓ ↙ ↓
[API Layer — JSON, stateless]
↓
[Business Logic / Services]
↓
[Data Layer — MySQL, Redis]The website became a consumer of the API, just like the mobile apps. This felt inefficient at first — why add a network hop for server-rendered pages? But the benefits compounded quickly.
Multi-Platform Reality
TouchNote shipped on:
- ·iOS (Objective-C, then Swift)
- ·Android (Java)
- ·HP webOS (JavaScript-based, fascinating platform — Palm's OS that HP acquired)
- ·Symbian (Nokia's platform, still significant in 2011)
Each platform had different UI paradigms, different performance characteristics, and different API consumption patterns. HP webOS was particularly interesting — it had a JavaScript runtime for apps with access to phone hardware, years before Node.js made server-side JavaScript mainstream. The card-based UI metaphor was genuinely innovative.
Having a single, well-designed API meant each platform team could move independently. The iOS team could iterate their UI without worrying about the Android team's requirements. The webOS app's experimental features didn't risk the stability of the iOS app's checkout flow.
The ZendMVC Foundation
The API rebuild used ZendMVC (Zend Framework's MVC layer). At the time, it was the most mature PHP framework for building structured, testable applications. Its modular architecture let us organise the codebase by domain — orders, subscriptions, products, users — rather than by technical layer.
The structured routing, dependency injection container, and well-defined controller/model separation were a revelation after the legacy codebase. If you're evaluating PHP frameworks today, ZendMVC's modern successor (Laminas) still has the same qualities that made it valuable then.
What I Tell Teams Today
Build your API first, as if the web UI doesn't exist. Make it stateless. Version it from day one (/v1/). Then build your web UI as an API client. The discipline this imposes on your architecture pays dividends when mobile, third-party integrations, and partner APIs come — and they always come.