Blue background with pattern

The first PWA on Deity Falcon for Publisher Pluim

Peter Jaap BlaakmeerOrange dotJul 8, 2019

13 min read

Last week we launched our first PWA project for a Magento 2 project. In this blog post we explain why and how we built this sophisticated and lightning-fast webshop. If you can't wait to see the result (we totally understand!) you can visit the webshop here; uitgeverijpluim.nl.

In the Magento PWA scene, there has been a lot of talk and little action regarding actually building shops. We've seen proof of concepts, but that doesn't get you anywhere. So when we had the opportunity to build a PWA shop, we decided to just go for it and see where we would end up. We were lucky enough to come across a client who was willing to take on this adventure with us!

Customer requirements

When the client approached us, they had no idea what a PWA was and what it entailed. Publisher Pluim is a Dutch publishing company that started in 2018. They publish literary fiction and non-fiction books aimed at the Dutch market. We pitched them PWA and explained what it could do for them. Two of the main advantages of PWA are the speed of the webshop and the high Google Pagespeed Insight scores that are relatively easily achievable compared to a standard Magento 2 frontend implementation.

The requirements were pretty straightforward, which gave us the confidence to start building a PWA. Currently, PWAs are not as feature-rich as the standard Magento 2 frontend, and equivalent features are still a long way off. The main initial requirements for phase 1 were

  • Ability to show authors
  • Ability to display books
  • Ability to display upcoming agenda items
  • Ability to display news items
  • Easily maintainable
  • Quick website

The following requirements for phase 2 were;

  • Ability to sell products
  • Ability to use iDeal as a payment method
  • Possibility of basic email marketing

Because of the relatively small amount of books in the shop (about 20 to 50 at any given time), we could do without filter options and search function. Because of the limitation to the Dutch-speaking market, we could also do without internationalization and complex tax settings, etc.

We then began looking for ways to separate these two phases and get the content site (without e-commerce functionality) online as quickly as possible.

React

First, we talk about our underlying tech stack. We are traditionally a PHP agency - we've always worked with Magento and a few years ago we started developing microservices and support tools for e-commerce in Laravel, which is also a PHP framework (but not specifically focused on any particular type of web app). Our frontend stack has always just been HTML/JS/CSS (and XML with respect to Magento).

PWA offerings, however, are not built in PHP. They are written in Javascript and, more specifically, in a Javascript front-end framework. There are two major players here: Vue and React. We considered both and ultimately chose React. I won't go into detail about why we chose React over Vue; you can read up on that choice yourself. In the end, it comes down to personal preference (and arguing often sounds like a religious debate).

Gatsby

After deciding to work with React a while ago, we started playing around with building pure React apps (like our tableratesgenerator.com) and building sites using Gatsby, which is a React-based static site generator. In fact, the site you're reading this on is built on Gatsby. Gatsby allows us to efficiently and quickly build extremely fast sites in a relatively short time and without much training for developers. React components are ultimately just little bundles of Javascript, making it quite easy for anyone with some Javascript experience to understand what is going on in such a framework. Moreover, the Gatsby docs are just excellent and the community is very welcoming (hello Jason!).

Since the first milestone was to get a content site up and running, we decided to go for Gatsby to get the site up and running. We had a design in pure HTML/JS/CSS and rewrote it into a Gatsby theme, which is basically a collection of React components. This allowed us to later port these components to our PWA solution with relative ease, since we also chose React when we went the PWA route for e-commerce.

The Gatsby site is still accessible here.

Prismic

Now it is time to introduce Prismic. Prismic is one of many interesting headless CMS offerings. A headless CMS is a content management system that allows you to manage your content without having any say in how that content is presented on the frontend. For example, if you use Wordpress without a frontend, but only use the Wordpress API to pull your data from the Wordpress backend and display it in your own custom frontend, you're essentially using it as a headless CMS.

We did a fairly in-depth comparison between a number of headless CMS providers such as Prismic, Sanity, Contentful, ButterCMS and Cockpit. This comparison could be a blog post in itself, but in summary we chose Prismic because of its price point (cheap but not too cheap), feature set (fairly complete) and their responsiveness to our inquiries (very fast). We also wanted a hosted SaaS solution (to minimize overhead), so self-hosted solutions were not considered. Contentful is a great option but insanely expensive.

Setting up Prismic is a very pleasant process; their backend is fast and pleasing to the eye. Their documentation is extensive and thorough, and above all, the amount of libraries and tools they offer in a wide variety of languages and frameworks is unmatched. This seems to be a typically French thing, as the Algolia integrations are just as endless. In particular, the NodeJS and React components for Prismic.io were real time savers during our project.

Prismic also provides a GraphQL API endpoint that we used to extract data from it.

Once we set up Prismic, we asked the customer to enter all the data. We created custom types for a number of entities;

Screenshot of Prismic custom types overview

We then linked Prismic to Gatsby via the gatsby-source-prismic package to make all the data available in our Gatsby site. Since Gatsby builds a static site and does not require a server after it is implemented, we used Netlify for (free!) hosting of the site.

Magento 2

On to e-commerce! By this time we had the content site almost ready to go, but we needed to display products on the site, albeit without e-commerce functionality. We set up a fairly standard Magento 2 instance and configured it so the client could add products to it. After they uploaded their products into Magento, we were able to use the gatsby-source-magento2 to retrieve product data from Magento 2.3 via GraphQL.

Deity Falcon

This is where the magic happens. We created all the conditions to get started with the PWA implementation; we had a Magento 2 instance with product data and a Prismic instance with all the other content, such as authors, calendar items, news items and content pages. We wanted to work in React so we could port the components we had already written in Gatsby to the PWA solution. We wanted to work in React so we could port the components we had already written in Gatsby to the PWA solution. We had some pleasant conversations with Eindhoven-based Deity, which develops a range of products for e-commerce, including Falcon and PushPro.

Their Falcon product is a PWA solution written in React that consists of two main components; Falcon Server and Falcon Client. Falcon Server acts as the glue between our backend systems (such as Magento and Prismic) and the frontend. The frontend in this case is Falcon Client, but the system is set up independently - we could have chosen to use our Gatsby site as the frontend and use Falcon Server to introduce e-commerce functionality into our project.

So why did we choose to implement our design in Falcon Client rather than e-commerce functionality in the form of a Falcon Server implementation in Gatsby? Because we already had many custom React components written in Gatsby, it was fairly easy to port this over. We also had no dependency regarding data, as this was abstracted in Magento and Prismic. We guessed that this was less work than writing our own implementation of Falcon Server for Gatsby, and in retrospect, it looks like we made the right choice, at least in terms of time. Note that we did not use Falcon UI, which is a UI component library for React. This is because we did not build the design from scratch; we had already converted it to plain HTML/JS/CSS. Falcon UI would be an option to use when we still needed to convert the design from Figma to code, in addition to other UI component library such as Storybook.

Custom work in Falcon API providers

Until now, the only major chunk of custom development work had to do with the frontend. But getting Prismic data to Falcon Server was something that hadn't been done before; we had to write our own sourcing packages. We ended up writing 5 API providers to source the 5 custom content types from Prismic (Calendar, Author, Homepage, News, Page). Books were already sourced from Magento through Falcon's Magento 2 module, although we had to write an extension to pass custom fields from Magento through Falcon Server to Falcon Client (see the Deity Falcon data flow diagram):

Sitemap generator

We also wrote a sitemap generator in Falcon Server. We couldn't use the Magento 2 sitemap because it would give us the Magento URLs for the products instead of the Falcon URLs and it would only have URLs for the books, but we have 5 other content types that we want indexed as well. Falcon Server is the place to do this; this is the only system that is aware of all the routes available within the site. We will be open-sourcing this sitemap generator soon, so keep an eye on our Github page.

Images CDN

Then we had the issue of images; we had images coming in from Magento and we had images coming in from Prismic. This would essentially work fine, but we wanted a single repository to manage these images and we wanted to implement a CDN for images. We decided to go with Cloudinary because we had heard good things and they have a great Magento 2 extension. By using this extension, Magento would return us the Cloudinary version of the product image, but Prismic does not do this. Therefore, we wrote our @elgentos/cloudinary-automatic-image-uploader package for Falcon Server. When we receive an image URL from Prismic, we hash it and check if a corresponding file exists in Cloudinary. If yes, we return that URL. If not, we upload it to Cloudinary using their NodeJS SDK and retrieve the resulting Cloudinary URL. One of the (many) cool things is that we can apply face image transformation for the author photos, so Cloudinary automatically crops to the author's face.

iDeal payment method integration

Out of the box, Falcon offers a PayPal and an Adyen integration. Unfortunately, the Adyen integration only offers a credit card implementation and no iDeal integration, which we needed. We wanted to go for a simple iDeal payment implementation and chose Mollie because of their extremely simple API and their great Magento 2 extension. The Magento 2 extension actually does all the heavy lifting; we just had to extend the extension a bit to pass another redirect URL. This is because we need to redirect the customer back to the Falcon frontend instead of the default Magento 2 frontend. You can find us on our Github page; Falcon Mollie implementation for Magento 2.

Pagespeed Insights optimization

We wanted a fast site, and a fast site is what we got! We spent a lot of time optimizing the code and the Webpack bundles that make up our final site, but here is the result (and yes, we are quite proud of it!);

Hosting

We have long been fans of Byte's Hypernode offering and run all of our Magento websites on that platform. Since this is a relatively lightweight site, we wanted to be able to run the entire stack on a single Hypernode. This had its challenges because, of course, we were the first ones to try this. Hypernode is a managed platform, so we didn't have a completely free hand to set everything up to our liking. But we got great help from Hypernode's support team and we got it working. In short, here is some of the work we had to do to make our Hypernode compatible with Falcon;

  • Install Node and yarn (or npm)
  • Set up crons that will start the Falcon client and server when not running
  • Configure Nginx so that it passes port 80/443 proxy to port 3000 (on which Falcon client runs)
  • Configure Nginx so that the Magento site will be available on a sub-subdomain (magento.projectname.hypernode.io)
  • Redirect www to non-www
  • Redirect http to https

Hours

How long did all this take? We had a start-up period where the customer defined their requirements, created content, etc. We started building the Gatsby site in mid-April, building the Falcon shop in mid-May and we launched the shop on July 4. Here is a visual overview;

Here is a breakdown of the major project components we discussed;

Component Sub-component Hours

Magento 2 setup 9

Prismic setup 17

Gatsby implementation 48

Falcon implementation total 250

Prismic 65

Cloudinary 32

Mollie 16

Hosting 7

CI/CD setup 4

Sitemap generator 2

Other 124

Project Management 20

Total 344

Conclusion

All in all, we are very happy with our process and how the web shop turned out. We learned a lot and feel we could do a similar project in half the time (don't blame us ;-)). Developing in Falcon/React was a bit of a learning curve because we came from the PHP world. Falcon is not bug-free or feature-complete yet, but the team is working hard and they are very responsive to Slack. They listen to feedback and implement suggested changes pretty quickly. We are extremely proud to have launched the first Deity Falcon webshop on their new architecture, and we are excited to see what the future holds!