Build Your Own E-Commerce Keystone.js-Based System — Requirements and Architecture | by Maciej Krawczyk | Mar, 2022

I believe there’s a need for a bit of clarification. This three-layered model does not relate to software architecture. We can still create microservices architecture using it, and we can stick to old but gold monolithic model.

My main goal here is to exercise skills in the design and implementation of a working system (and write about it), not to get involved in the theoretical discussion of the superiority of one approach over another.

Now it’s time to talk about all the elements building each separate layer but also about connections between them. Although I’m going to give a brief analysis and description of each layer in this article, I’ll mainly focus on the logic layer.

Presentational layer elements

The frontend layer will be built from three main elements: main app, Next.js application in this case, and CDN service and Nginx web server.

It’s a rather straightforward solution: the main app built in React with the help of the server site rendering from Next.js creates a kind of sweet spot with single page application interaction — and has all of the SEO advantages and faster initial loads from server- side rendering.

The role of the CDN here is to help with serving static files, mostly images. Nginx works like a reversed proxy and load balancer. Nothing too complicated. All the communication with the logic layer happens via GraphQL.

Logic layer elements

This main layer basically contains only two elements: The Keystone.js app working as main processing, and the command unit and GraphQL resolver, which act as an extension to the built-in one and work as a wrapper for text search capabilities for the underlying search engine.

But this statement is a huge simplification, so let’s get to the details.

Keystone manages three models fundamental for the whole system: User, Productand Order.

The rest of the models can be directly or indirectly derived from them. First, User Holds the basic information of customers and staff of our e-commerce system, mainly authorization info and assigned roles.

Also User has one Cart and can have multiple Order models and multiple Address models. Each Order model has one connected Payment and Shipment and holds multiple Product models.

Product has one Stock model (for the sake of simplicity, we assume we won’t use a multi-warehouse setup) and multiple ProductImage models.

Lastly, it has a connection to multiple Category models, and each one of them can be related to the parent Category forming tree.

It looks complicated, but it’s not (yet).

Basic models structure

Also, the role of Keystone is to manage the content of basic pages for the main frontend app. But more important, its role is also to manage side effects and external integrations.

An example of this side effect may be e-mail notifications associated with order processing steps and informing clients about it or indexing products data in search engines after changes.

On the other hand, examples of external integrations contain the usage of Stripe in order to process payments or connect to external API handling delivery (eg, DHL API).

These functionalities will mainly harness the power of hooks in Keystone schemas. But not only that, we will need to create additional rest endpoints as webhooks in order to handle async responses from these integrations.

Lastl, Keystone admin UI works here as a kind of dashboard for staff to manage orders and process them.

Data layer elements

The last layer of the system’s main responsibility is to collect data and ensure its persistence. Like in the previous one, there will be two elements here: PostgreSQL database and Meilisearch search engine.

For the moment, I’m writing this with no choice of the database. Keystone.js supports only PostgreSQL or SQLite, and I believe the second one is a bit too small for e-commerce system.

For the search engine, we need custom integration, so the choice here is much bigger, but I’m most familiar with Elasticsearch and Meilisearch.

I decided to choose the second one because I feel its JavaScript integration is a little better, and querying using facet filters is easier. Additionally, its footprint is a couple of times smaller than Elastic.

That concludes all the elements of our yet to be built e-commerce system:

System overview

Ok, let’s sum up. Now we have the basic overview of what we are going to build in the next part of this series.

Building an e-commerce system may look hard and daunting, but when we split this task into small, well-planned chunks, it’s not so terrifying.

Next time, we will write a little code and start with the project’s setup.

I hope you liked it. If you have any questions or comments, feel free to ask them.

Have a nice day!

Leave a Comment