Front Page Redesign

Technical Overview

Warning: the following presentation contains technical jargon and assumes an unfair level of familiarity with technologies including, but not limited to: JavaScript, React, Node.js, Morph, HTML, CSS, Web Browsers, HTTP, TCP, Unix, Data Structures, Type Systems, Lambda Calculus, Category Theory, Register-Based Virtual Machines, Hardware Virtualisation, Field Programmable Gate Arrays, CPU Register Access Optimisation, Memory Throughput Bottlenecks, I'm genuinely just making stuff up now...

Made from horizontal "slices"

  • Each section (top stories, must see, most watched, ...) is an independent slice
  • Slices are intended to be themed and reused across BBC products
  • Drastically simpler layout thanks to removed secondary column

Slices built in React

  • Each slice is an independent React component
  • Modular design: common UI components are shared across slices
  • Most slices are higher-order components to enable reuse by other teams
  • We don't run React in the browser! More on this later

Styled with Grandstand

  • Small CSS framework shared between Live, Sport, News, World Service, Weather, Politics, Local, ...
  • Uses GEL grid & typography which are shared by even more BBC teams
  • Provides primitive utility classes rather than bespoke styles for each component (more on why this is important later)

Delivered by Mozart

  • Page assembly service developed by News Frameworks
  • Slices are fetched as HTML from Morph's React-component-as-an-endpoint API
  • Inline styles are de-duplicated
  • Slice HTML is rendered in order into a bare-bones page template

It's fast!

  • Content is rendered 40% faster
  • 85% less CSS (860KB → 125KB)
  • 90% less JS (290KB → 15KB)
  • 30% more HTML but 4% less after gzip
  • Plans to make it faster (even less CSS, better stylesheet bootstrapping mechanism)

Less CSS with Grandstand

  • Most designs can be implemented with the grid
  • Primitive utility classes means a lot (like, a lot) of classes in the HTML
  • But they are the same classes, so they compress really well
  • Modify designs to work with Grandstand rather than writing tonnes of bespoke CSS
.hard-news-unit__summary, .basic-information__body p, .forecast-daily__time, 
.forecast-hourly__time, .forecast-hourly .weather-temperature, .media-feed-item .cta, 
.media-asset-page .story-body .introduction, .live-event-index__summary, 
.live-event-index-item__breaking-news, .live-event-index-item__text, .sport-stories .tabs-list li a, 
.sport-teams-unit__list-item-link, .from-other-news-sites-list-item__source, 
.visual-promo-label__summary, .visual-promo-content__summary, .programme-promo-summary, 
.top-stories-promo-story__summary, .more-from-this-index__link-title, .most-popular__header__tabs li a, 
.most-popular-by-day__list-item-day, .most-popular-by-day__list-item-title, 
.correspondent-promo__article-summary, .digest-list, .navigation--wide, .secondary-navigation--wide, 
.markets-selector-item__link, .markets-index-dropdown-list-item, .markets-index-table thead th, 
.markets-index-table tbody td, .comments-explainer-line, .find-local-overlay__current-location, 
.find-local-overlay__done, .find-local-overlay__cancel, .find-local-overlay #locator-geolocation .link-text, 
.find-local-overlay #locator-search-input, .find-local-overlay #locator #locator-results a, 
.contributor__name, .update__body, .tv-bulletin__summary, .ws-promo__more, .albatross__summary, 
.bold-image-promo__summary, .budgie__summary, .buzzard__summary, .capercaillie .constituency-azlink__link, 
.dove-item__summary, .eagle-item__summary, .election2016-azlink__link, .ni2017-previous-results__link, 
.results-banner__abbr, .results-banner__value, .election2016-results-graph__link, .results-ticker__headline, 
.gallery-images__summary, .heron__item-summary, .kestrel__summary, .loon-item__summary, 
.merlin__summary, .nations-pseudo-nav__link-inner, .osprey__summary, .parakeet-lead-item__summary, 
.parakeet-item__summary, .penguin__item .title-link__title, .pigeon-item__summary, .pukeko-item--stacked .pukeko-item__summary, 
.quetzal__summary, .related-content-links__link, .raven-item__summary, .shoebill-lead-item .title-link, 
.shoebill-lead-item .title-link__title-text, .shoebill-item .title-link, .shoebill-item .title-link__title-text, 
.skylark__summary, .small-image-promo__title, .sparrow-item__summary, .spoonbill-item .title-link__title-text, 
.comp-stream .story-body__list-item, .local-survey, .comp-stream .quote--email, 
.comp-stream .quote--sms, .swift__entry, .swift-source__name, .waterfowl__link--duration, 
.waterfowl__item .title-link, .waterfowl-heading__title {
    font-size: 14px;
    font-size: 0.875rem;
    line-height: 1.28572;
.gel-brevier {
  font-size: 14px;
  font-size: 0.875rem;
  line-height: 16px;
  line-height: 1rem;

Bespoke component styles


Typography settings

↑ rampant abuse of Sass @include

No React in the browser

  • Recap: each slice is a React component
  • Slices can depend on big third-party libraries like Lodash, Moment.js
  • Entire dependency tree must be sent to the browser for slices to render
  • Equates to almost 2MB of JS
  • 100% CPU usage for >20 seconds on low-end devices

Case study: lx-stream

What's next? (Product)

  • Roll it out to domestic users
  • Finish off the international edition
  • "Special treatment" promos
  • Slice library

What's next? (Technology)

  • Work with Morph to improve style bootstrap performance
  • Slim down Grandstand
  • Investigate running Preact or Inferno in the browser
  • Investigate using styled-components

Thanks 💚

Made with