Bespoke Publishing Platform
Raconteur is a London-based publisher for special-interest content for business leaders, well known for their infographics and special reports in The Times / The Sunday Times newspaper. I have been working as part of their creative division in a small engineering team. When I first joined Raconteur the key objective was to move their WordPress-based monolithic solutions to a React-based modern structure.
The project
Raconteur Insights is a bespoke publishing platform I have developed in-house alongside their UX team. The challenge was, that designers were developing animated infographics using Tumult Hype. These consisted of a HTML document and an embedded script file, that was bundled and uploaded to an SFTP server.
The overall content structure would always be the same, but there are various different types of content that are collated for a given report. Each report has an intro screen, displaying an animation and the title of the report, followed by a table of contents. This is followed up by articles and infographics, sorted in a predefined order.
The aspiration of Raconteur Insights was that this would feel like a print publication with the added benefit of dynamic animations. The design team consisting of print designers and one UX designer had very specific expectations that needed to be met.
The first approach
Since this was a greenfield project, none of the systems design decisions have been made, so I started from scratch.
What we knew:
- We wanted to build a custom publishing platform
- The technology stack should be based on React
- All other systems are based on WordPress
- Animations are done by the design team in Tumult Hype
What we had to work out:
- Is WordPress the right tool for this headless implementation?
- How regularly are we publishing these dynamic reports? → Do we want to build a server-side rendered (SSR) application or static pages (performance benefits)
- What are the business requirements for test coverage and maintainability?
- How do we bring our Hype animations into a React app?
- How do we host the app?
Based on these questions I started a week-long spike into how best to structure the app. First I was looking at the meta frameworks Next.js and Gatsby. At the time Next.js did not have good support for SSG (static-site generation) and Gatsby did not have support for SSR (server-side rendering). After initial trials and weighing up pros and cons we decided to go down the route of statically generated pages using Gatsby. The primary deciding factor here was the fact, that we intended to create one report per month, keeping the necessity for rebuilds quite low and build times under 10 minutes per month. Had we decided to publish more frequently (say once a day), we would have preferred Next.js’ SSR approach, since the length of Gatsby’s builds would increase significantly after around 9-12 months.
Another deciding factor for Gatsby was, that at the time, Gatsby had the best support for TypeScript, which was an appealing choice to make sure we have a type-safe system in place. In addition we chose to add unit- and integration tests with Jest.
The next decision I had to make was for a content management system. Since all other websites Raconteur manages were based on WordPress (some headless, some monolithic), this seemed like the obvious choice. However, after looking into the custom post types we required to make this publishing platform work as intended, we would have had to utilise Advanced Custom Fields to a large extent and the RESTful API availability within ACF was rather limited at the time and would have led to constant over-fetching of data. For that reason we decided to look at different headless-first CMS solutions. The ones I looked at and trialed are:
- Contentful
- Sanity
- Prismic
- Strapi
All of these systems seemed very appealing for different reasons, however we decided early on, that we did not want to maintain a self-hosted CMS outside of our WordPress host, so Strapi was ruled out early, despite being open-source and very appealing otherwise.
After some research and testing all these CMS’s and comparing pricing and features, we decided to use Contentful for Raconteur Insights.
The next question to answer: what about Hype animations? I had been thinking of the best way to bring these into our app since the very beginning and after some investigation I noticed, that the HTML structure is always the same, just the script would be different for each animation. Therefore the component structure was quite straight forward:
export default function HypeAnimation({ animationName, slug }: IProps) {// When mounted, get the container and create a script element with the link to the SFTP hosted hype fileuseEffect(() => {const container: HTMLElement = document.getElementById(`${animationName}_hype_container`);const script = document.createElement("script");script.src = `https://${process.env.SFTP_PATH}/${slug}/${animationName}/${animationName}.hyperesources/${animationName}_hype_generated_script.js`;script.async = true;container.appendChild(script);}, [])// Return a div with the correct structure for the hype animationreturn (<divid={`${animationName}_hype_container`}className="HYPE_document"/>);}
This way we would be able to insert any amount of animated infographics with the least amount of effort and impact on performance.