It’s been almost three years since we started building Seller, an eCommerce solution built for African small and medium businesses to help them run and manage their businesses online. Seller helps entrepreneurs manage their orders, inventory, customers, payment, shipping, marketing and a host of other activities. The platform also provides them with a customizable and easy to use storefront solution to help showcase their brand and offer their customers a seamless shopping and checkout experience.
It was an interesting time being part of a young engineering team tasked with building such a platform from scratch, especially without any prior experience at such scale. Nevertheless, we were super excited and fired up, ready to take the challenge head on!
Before we got started, we had to ask ourselves some major questions; how would we build dynamic storefronts? How would they be customized and what level of customization would we be offering? What would themes look like and how would they be built, stored and modified? Those were hard questions at the time and we didn’t have any answers, nor did anyone else on the internet, well at least not directly.
We had to start somewhere so we started by picking a framework. Engineers and tech enthusiasts probably know the framework debate all too well and at the time it was React vs Vue (still kind of is). From our research, we found that Vue performed well at scale, had a refined reactivity system, robust single-file components, a versatile and adaptable ecosystem and the promise of an enjoyable developer experience.
Ultimately, Vue won the debate for us because of all those reasons, plus it was relatively new at the time, had some buzz around it and didn’t have such a steep learning curve; the latter of which was important as a lean team planning to onboard more engineers just starting out their careers.
With our Javascript framework out of the way, we still had more decisions to make — what CSS framework would we use? What UI component framework would we use? And so on. It’s important to note that we were on a time crunch to deliver an MVP, so we tried to rely on as much open source/templates as we could. There were so many options to choose from; Bootstrap, Bulma, Tachyons, Foundation; the list was long. We went with Bootstrap, it was 2019 and Bootstrap was king. For our component framework, again we had lots of options. Initially we chose Bootstrap-Vue (obvious choice) but eventually moved to Ant Design (still one of the best out there). Finally, for state management, we went with Vuex, the only option available other than building a custom state machine. With all that initial decision making done, it was time to start building (in retrospect, should have been time for more planning 😬).
Building eCommerce, for us, largely entailed building a dashboard for managing inventory, orders, integrating payment providers and shipping services as well as building customer facing storefronts to display inventory and receive orders and payments from customers, and finally a customizer for designing and theming the storefronts.
Our initial dashboard solution was a Bootstrap/Vue template that we had to customize to meet our requirements. This approach didn’t end well for us because there were tons and tons of unwanted and unused code that we had to go through just to maintain the app. Adding new features was hard and we were also forced to use a lot of packages that were added as dependencies. Ultimately, we abandoned that version of the dashboard and our product and design team had to rethink and redesign a new version from scratch.
For our storefront and customizer solution, our Vue implementation relied heavily on state management. Initially, we managed the theme state with Vuex and had to build an event bus to trigger theme changes by calling multiple mutations. We had individual mutations for every item within the state and had to organize their mutations within the event bus based on each theme (cringe, I know). This worked for a while, but obviously could not scale. For the next version, we had to organize the state better and use single actions to make multiple mutations to sections within the state. This made it easier to change and apply different theme states across the application.
Benefitting from an evolving Vue ecosystem
Vue 3
As Vue continued to mature, there were a lot of changes and improvements to the framework and ecosystem at large, starting with the introduction of the Composition API and a new version of the framework. We were already halfway into the development of Seller 2.0 when Vue 3 was released and we didn’t waste any time migrating to it.
Vite
Before Vite, we used Vue CLI to manage our build configuration and Webpack bundling. We migrated to Vite at the same time as we did Vue 3 and saw signifcant improvements to our application cold start bootup time as well as improved compilation speed during development!
Pinia
Pinia is Vue’s new core state management solution that replaces Vuex. We picked up Pinia right away as it offered a brand new API more suitable to use with the Composition API. Pinia also reduced a lot of the complexities that came with Vuex, some which included the removal of mutations, removal of name-spaced and nested modules, Javascript auto-completion, native Typescript and SSR support, dynamically imported stores and more. Overall Pinia was just more delightful to use and made state management a breeze!
VueUse
Prior to VueUse, certain features were a chore and a source of numerous bugs for us, but thanks to this utility library, we put all of that in the past. VueUse is a set of composable utility functions for your Vue app. It comes packed with tons of core browser, sensor, animation, state, network and a host of other functions. Reactive breakpoints, reactive CSS, reactive browser titles, reactive favicons, reactive storage…you get the point, pretty much every core feature is reactive, easy and ready to use with VueUse.
Nuxt 3
One of the most unpleasant experiences building the platform was definitely handling SSR. In retrospect, we didn’t spend enough time learning how SSR in Vue actually works under the hood and the common pitfalls to avoid. Before Nuxt, we had tried using Gridsome, another Vue-flavoured SSR framework; it had some limitations, most notably the inability to use some of our core dependencies as well as some deployment issues.
We tried SSR again with Nuxt 2 and the experience was much better, it featured a rich API, better documentation, a growing module ecosystem and host of other features to help build a performant server-side rendered Vue application. We were satisfied with our Nuxt 2 setup and patiently waited for the release of Nuxt 3 which promised to be even better than its predecessor. We didn’t have to wait long before the beta version arrived, and it was indeed worth the wait.
Continuing with our trend of trying new things as soon as they come out, we hopped on it right away, and boy did it pack a punch.
Nuxt 3 is the ultimate Vue framework that features a brand new server engine, a lightning fast Vite bundler, hybrid rendering modes (client, server and universal rendering), native Typescript support, inbuilt Head and State management, inbuilt client and server routing, auto imports, data fetching in Suspense mode, a ton more plus all the awesome features from the previous version turnt up, phew! We intend to fully migrate our storefronts to Nuxt 3 as soon as it has a stable release!
Vue DevTools
Your Vue developer experience is not complete without using Vue DevTools.
Vue DevTools is the official companion tool for building and debugging Vue applications. It’s a fast, sleek and reactive way to interact with your app and a great tool for seeing what’s really going on inside your app. It features an Inspector tool; which shows you a collapsible view of your component hierarchy along with their internal states, props and events, an exploratory list of all your stores (supports both Vuex and Pinia) and a complete view of your router and the routes within it. It also has a neat Timeline view of mouse, keyboard and component events; as well as performance, store and router events. This made finding bugs, testing new features and exploring use cases such a blissful experience!
Tailwind
This essay wouldn’t be complete without talking about Tailwind. Migrating from Bootstrap to Tailwind was probably one of the best decisions we made while building our platform. When Tailwind was first introduced to the team by one of our engineers, it was met with a bit of resistance because we had recently just experienced the pains of having to update styles with classes. Eventually, we tried it out and completely loved it. We also used a bit of Tailwind UI in V2 of our storefronts (an absolute time-saver and productivity booster!).
Summary
I’m glad we made the decision to build with Vue. Unlike other frameworks that try to be as un-opinionated as possible by giving developers the choice of doing the same things in multiple different ways, thereby increasing complexity, likelihood of bugs and an increased engineering time; Vue shines by abstracting away a lot those complexities, reduces unnecessary decision making/engineering time, provides a simple and robust set of API’s, boasts of a solid base of core libraries in its ecosystem and offers the support of a rapidly growing and vibrant community.
Vue offers developers the time, freedom and focus they need to plan, design, architect and engineer their applications without having to worry too much about building and maintaining things under the hood. Building with Vue is really as awesome as it claims to be 🔥🔥🔥!
In a nutshell, those are the tools we leveraged on to build our eCommerce front-end architecture and some of the lessons we learnt along the way; and as you can see, it was a bumpy road but we sure had fun building it.
Huge shout-out to the Vue community 💚, open-source (OSS) contributors and our past and present engineering team for helping make this a reality; thank you, you rock!