UX never felt this good: Technology behind Satoshi

ScandiPWA
5 min readNov 29, 2023

--

Satoshi is the next benchmark of modern UX for eCommerce — a tangible demonstration of a web-based app you want to keep browsing. Welcome to a deep-dive article covering the technology behind Satoshi, scandiweb’s special book of industry secrets.

Join a Q&A session hosted by our CTO and Satoshi creator, Alfreds Genkins, on December 12 at 1:00 p.m. GMT!

Just as ScandiPWA originated from the innovative sandbox of scandiweb, Satoshi is the next evolutionary phase emerging from there. Although it isn’t yet a fully integrated ScandiPWA theme connected to Magento’s backend, it stands as a guiding North Star that we believe any project should aim for and the type of the UX that ScandiPWA users should get.

Design system

At the heart of Satoshi is a solid design system. A design system provides developers with carefully selected properties to use across the application: font sizes, spacing, colors, border radiuses. UI components and layouts are using these and only these properties. Such opinionated limitation allows for a feeling of consistency across the final product. An introduced abstraction layer helps to speed up client-specific customization, and builds a great foundation for UI designers.

The current styled system implementation uses a themed Chakra UI. It provides a solid foundation for consistent styling, through its powerful styled system. We chose Chakra UI for its attention to detail, which aligned well with our vision.

However, the Chakra UI is utilizing a runtime CSS-in-JS solution (emotion) to provide styles. It is amazing from a developer-experience perspective (apply styles through React element props). This library is very CPU intensive, leading to a high amount of long tasks in the main thread, negatively affecting the Total Blocking Time (TBT) metrics.

We have some ideas on how to improve the performance of emotion on initial load, however, if nothing helps, we might migrate to Chakra UI logical successor Ark UI, or build our own library using the Panda CSS (replacement for Emotion), Zag JS (state machine), or Radix UI (unstyled component library).

Interaction & animation

It is known that for website animations to look and feel good, the animations must be made in a way that would not cause a reflow, AKA by using the “transform” CSS property. Additionally, the main thread should be kept free. CSS animations run better with component rendering optimized, thus we aimed to deliver exceptional rendering performance.

To make sure critical interactions and animations (ones taking more than half of the screen) work exceptionally smoothly, we opted not to use animation libraries for them. We are especially proud of the modal animation, image zoom, scroll lock, and “shared element” page transition implementations. They all were implemented in pure React, keeping the update count as low as possible.

For UI components and micro-interactions, we used a Framer Motion library. We did not choose it, it came bundled with Chakra UI. We are unhappy with its impact on the final bundle size. Currently, it takes up to 20% of the total bundle. It is one of the contributing reasons to migrate away from the Chakra UI library.

Out of all Framer Motion features, the application utilizes the layout and presence animation the most. This means, that to remove this library, an alternative solution is to be found or implemented.

State management

The application does not utilize a state management library. Instead, it provides all the necessary values through a context, a native React feature. This means, there is no prop drilling within the application, and there is no bundle-size overhead, as the native React features are used to make the state management work.

However, because we have used the compound objects in our context value (not atomic values), the single change of context value causes all listeners to re-render. This is not ideal, especially considering the importance of keeping the main thread free for animations to play smoothly. Additionally, the debugging of actions is unreasonably complex at the moment.

Most of our state is global, however, sometimes there could be multiple instances of the same store across the website (like in the case of products and categories). We are considering a migration to Redux, utilizing its multiple-state feature.

Server-side rendering

Great search engine optimization (SEO) and Core Web Vitals (CWV) is very hard to achieve using client-side rendering. Therefore, we opted to use server-side rendering. However, the app was initially prototyped using React Router and used a history state (to persist critical data between pages). We wanted a compatible solution, to avoid migrating to a different router implementation.

We chose Remix, an alternative to NextJS (when it comes to rendering React on a server). And we are quite happy with the choice. We had modified it a bit to suit our needs (specifically offer an optimistic navigation) if there is already enough data to load the next page. This is exciting, as we can show the UI of the next page instantly, without waiting for Time To First Byte (TTFB).

The features offered by Remix are very exciting, and we specifically want to look at Remix actions and fetchers more, as a replacement for SWR hook. They seem to offer a more robust handling of errors, interruptions, and race conditions.

Build & deployment

We believe that a build of an application should be near instantaneous. Our goal was to build the application in under 10 seconds. We managed to do it, in 5, thanks to Vite and esbuild. We also utilize built-time optimizations like Million to make React rendering faster.

The application is currently deployed on a nano EC2 instance. However, it is mainly for historical reasons, that we initially planned this product as proof of concept. We believe the headless front end should run server-less.

We aim to migrate to CloudFlare edge workers, to improve page response time. The stale-while-revalidate caching directive could help us to improve load on servers, and further decrease response time.

Progressive Web Application (PWA)

If there is something we can offload to web workers to free up the main thread for animations we should. The Partytown utilizes the PWA features to eliminate the analytics overhead (and put it all into workers).

Useful links

Join a Q&A session hosted by our CTO and Satoshi creator, Alfreds Genkins, on December 12 at 1:00 p.m. GMT!

--

--