Slowly we have been expanding our On-Demand training portfolio and in the middle of all these offerings is the Yireo Courseware Portal: Because it's setup is a nice example of how to build a SaaS relying on Magento plus microservices, here's a peek in the kitchen.
The Yireo Courseware Portal
For some time (since early 2021), Yireo has been offering video courses, at this moment totalling up to 70 hours of video. Actually, we label them as On-Demand courses because the videos are backed with courseware (slides + notes + code), the courseware portal itself (with nifty features outlined below).
Magento at the core
The Magento 2 shop has been upgraded recently to 2.4.4 and PHP 8.1, which boosts performance. The current frontend is based on Luma still, but there are plans to migrate this either to Hyva or to headless, because the main Yireo website is Slim PHP anyway and React is scattered across pages. The focus of this blog is not on this ugly frontend, but rather on the specific React-based courseware pages (training.yireo.com/courseware).
The React frontend connects to the GraphQL API of Magento. However, most of the endpoints needed here are custom built. And some are connecting to microservices hidden behind Magento: The courseware supplier and the scheduler API. Magento is mainly sitting in front, because of authentication. I've been thinking about restructuring all of this, by using either Apollo Server or GraphQL Mesh as the entrypoint into the stack, which could then contact Magento for authentication and then filter out all unauthorized content from the other microservices.
My first training ever was given with slides written in SunOffice. But somewhere in a dark past (Joomla, Drupal, SugarCRM) I turned this into slides written in Markdown and converted into slides by using either RevealJS or RemarkJS. This has led to the current courseware microservice, a Symfony-based application that serves Markdown via GraphQL.
The courseware is divided into lessons, chapters, courses and course groups (like Magento or Shopware). Numerous query endpoints allow for fetching data. The current RemarkJS client that I use during live trainings will be replaced in the future with a React client (that uses GraphQL) which is already part of the Yireo Courseware Portal (based on Magento).
The focus of the courseware microservice is deliver any content as fast as possible. Usually calls take less than 20ms without caching, except for when Markdown is turned into HTML. Yet, the Magento app sits in between the client and this microservice to add authentication and authorization. GraphQL calls from React are literally proxies via Magento towards the courseware GraphQL API and then filtered. It adds overhead but works, often with GraphQL calls still taking less than 300ms (again, without caching and being customer-specific).
Another microservice is actually used by the Yireo Agenda which used to be flooded with live trainings, events like MageTestFest & React and other community events we would travel it. Currently, it is empty because of dad-life. However, apart from the upcoming events, there is also a need for past events, because students of past live trainings still get access to the courseware (alongside the On-Demand courses).
The scheduler microservice started off as a Zend Expressive microservice. But since Zend is dead, I migrated this to Slim PHP (which is also used for the main Yireo site). However, another trick to make the listing of trainings (including training dates, SKUs pointing towards Magento and a lot more) more performant was to dump the output to JSON files, which are still served by the scheduler microservice.
It might be that the internal architecture of this microservice is changing in the future, but the main point here will still be that the service is generating external JSON files for consumption in various React apps (the Yireo Agenda, the Yireo Courseware Portal) and services (Magento).
React app for courseware
I talked about React a couple of times, so it is maybe nice to point out the architecture for the Yireo Courseware Portal app: Well, it is React, does not use any CSS framework but reuses the vomit of earlier Yireo sites, uses functional components only with hooks and a simple global state via Context (so no Redux). The biggest dependency is Apollo Client, while I'm not using its features much, so I might be migrating this to a more lightweight library instead.
The outcome of all of this architecture is that I'm able to migrate specific parts from one application to another more easily. GraphQL is for some part the glue. But the glue is also heavily involving separate React apps that are driven by PHP applications (Symfony, Slim, Magento). SSR is not an issue here, SEO is not important. It is a simple architecture that is quite easy to maintain and extend.
The real goal here was that a custom platform would allow me to build my own custom features as well. Writing is done in Markdown, publishing requires seconds (some script pushing git changes), uploading videos is easy as well.
Within the Yireo Courseware Portal, the student also benefits: Courses can easily be searched, lessons can be marked in various ways. And slowly nifty features are also added: A video pointer is saved to the Magento database, so that the video continues where you left off. Diagrams show you the percentage at which the course has been completed by you. Little popups react to your progress and show hints. And there is much more planned as well.
All in all, I'm just really happy that I worked hard in creating a custom Yireo platform for this purpose. And together with the abundance of content that is available to you, I hope you can appreciate all that hard work!