Case Study: Migrating a legacy PHP app to Next.js at STV

  • PHP
  • HTML5
  • JestJS
  • ExpressJS
  • NodeJS
  • ReactJS
  • Redux
  • Next.js
  • CSS / SASS

Overview

Scottish Television (STV) is Scotland’s largest commercial broadcaster, with a flagship streaming service that serves over 10 million streams per month. This web product is a key aspect of STV’s digital presence, allowing them to reach a vast audience with on-demand television and live broadcasts.

Despite its success, the app had grown into a significant monolithic, making development and deployment increasingly difficult for the team. The team wanted to transition towards an architecture that would allow for more granular and flexible deployments. The codebase itself was diverse and somewhat fragmented, with parts built at different times using a variety of technologies. large parts of the codebase were rendered in PHP whilst other parts used React on the front-end

Due to the release of STV’s Android and iOS apps, a JSON data API had already been developed to serve as a backend for these applications. This set up meant that getting the Front-end team to assume responsibility for rendering of all view code seemed like a no-brainer, enabling the back-end team to concentrate on data management and infrastructure.

My initial role at STV was part of the news team, where I had been exploring ways to convert the web news app into a Progressive Web App (PWA). This exploration included a POC around using Next.js and a new Node.js infrastructure. With this foundation, I was moved over to help implement the migration of the main app to Next.js.

Problem

The existing app was extensive, incorporating many sub-applications that each addressed different functionalities of the platform. Fortunately, these sub-apps were organized under distinct top-level paths, which provided a degree of separation helpful for modular migration. However, Next.js was relatively new at the time and largely untested in a production environment, so the switch involved a degree of uncertainty and significant planning.

Transitioning to Next.js required infrastructure changes, including STV’s first deployment of a production Node.js application. This brought new considerations and the need for additional planning regarding the server architecture. The player code itself was sizable and complex, involving various elements like ad tech and analytics integrations, which had to be addressed carefully during migration.

Management was interested in understanding the direct benefits of such an involved development project from a consumer perspective, as the migration would require considerable development resources and commitment.

Solution

To address these challenges, we started with a simple proof of concept. First, we deployed a basic app in the real production infrastructure, running load tests using AWS’s “Bees with Machine Guns” tool to validate the app’s performance under expected traffic loads. This provided reassurance to management regarding scalability and helped demonstrate the infrastructure's reliability.

We adopted a design-first approach, as the app was in the midst of a design refresh. This allowed us to align the migration with the new design standards, ensuring a cohesive look and feel upon the app's launch and cut out any cruft that the stakeholders felt was no longer necessary.

Thanks to the well considered routing of the initial app, we could intercept requests at the infrastructure level, migrating the application incrementally, path by path.

/player
could still navigate to the legacy app, but
/summary/:programID
could be directed to the new Next.js app. We began by migrating simpler pages—such as the landing and listings pages, which primarily displayed static content like images—to help identify and resolve any early technical challenges (mostly around authentication, advertising integrations, and CORS)

The main video player application was relatively self-contained, making it feasible to migrate this section as an independent module. By deploying the video player as a standalone module that communicated with the top-level app via a message bus, we gained the ability to update this component incrementally without disrupting other parts of the service.

Given that some parts of the app were already written in React, this also made it easier to integrate these components into the new app structure.

Results & Impact

The migration provided an opportunity to streamline and modernize the codebase. Rewriting portions of the app allowed us to reconsider priorities, eliminate outdated code and unused utilities, and leverage new tools to build a leaner, more efficient codebase.

The adoption of styled React components fostered greater code reuse across the app. This made it easier to develop new parts of the application, not only for the main player but also for additional sub-apps, all while maintaining a consistent brand experience.

Building the app with modern React also enabled us to establish better test coverage, both at the unit and integration levels. This contributed to a more stable application with enhanced reliability over time.

The migration also brought significant performance improvements, reflected in a higher Lighthouse score across key metrics like Time to First Paint (TTFP), Time to First Interactive (TTFI), load times, bundle sizes, and accessibility (a11y). These performance gains translated into a smoother user experience, directly benefiting STV’s viewers. Improved page speed, which impacts revenue, was also tracked across deployments, enabling long-term performance monitoring.

Deployment times saw a considerable reduction, thanks to the more modular structure of the new architecture. Additionally, infrastructure usage was optimized; by caching pages on the front-end infrastructure, we reduced the load on the backend, further enhancing the app’s efficiency.