Building a full-stack e-commerce web app
Tags: ecommerce, beginners, javascript, node
Published: 2023-04-26 20:53:01

## Intro

This being my first post here, the point of it is not to teach anybody on how to build web apps, merely to share my journey and experience.

That being said, I have spent the better part of my free time in the last 6 months building a [fully-functional custom e-commerce web app](https://excessive.onrender.com/) for a friend. 

The application was built in accordance with the latest trends HTML5, CSS3 and JavaScript for the front-end, and nodeJS, mongoDB, Pug, with RESTful API for the server-side. PayPal API has been integrated for the payments. The reason I opted against using any frameworks or libraries for the front-end, why we decided on custom instead of ready-made solution and all the events that led to this post follows next...

## A bit of history first... 

Sometime during this pandemic I finally got fed up of the motivational, intellectual, cultural and financial stimulation (or lack thereof) offered by my current job and management, which has nothing to do with programming or IT. I finally felt it is time for a change and if I was gonna be changing something, I decided to revive my old interest and hobby - programming. Even though it has been a while since I have programmed anything, I have constantly kept myself occupied with IT projects and hobbies, so I never really drifted too far away from the subject. Added value - HTML, CSS and JS are now far more complete and capable of building a complete and useful web solutions, which definitely was not the case back in my student days, when you needed to use primitive workarounds like HTML tables for anything more complex than text paragraphs.

So, sometime at the beginning of last year I went ahead and invested in several courses on front and back-end development, watched dozens of free ones as well (to refresh my past knowledge and to get up to speed with the current state of these languages and tools) and when I finally felt confident that I can move on, I decided it's time to start work on a project. Everybody is different, somebody wants to tackle topic by topic, I work better and solve problems better if I have the full story (in this case the full-stack) in sight.

## Back to the project... 

This turned out to be complex project with a lot of functionality for such small shop, however it was a great learning experience and a great exercise. It challenged me to learn a lot of stuff that the courses do not usually cover, to think of all the ways in which you can group and organize the APIs, how to access them from the front-end in the most optimal way and most importantly.... to think of the design. Writing code is one thing, designing attractive and acceptable interfaces is something else. This is precisely the reason I opted against using libraries and frameworks for the front end, I simply wanted to play with and learn as much CSS properties as possible.

Going step by step and starting from the organization of files and algorithms, I went with MVC for this project. Even though there are different philosophies on organizing the code, for this project I applied the MVC structure, because it seems to be largely favored by web developers and because it suited the requirements for this project.

I basically built a bunch of backend API endpoints for product manipulation (adding, removing, updating etc.) I knew upfront I will definitely need, built the mongoose models and then went back and built a basic front end HTML frame (with minimal CSS), just to get a sense of positioning of elements, size, get a general idea of what everything would look like. 

After this, I went back and built the user authentication APIs (which was easy enough using JWT), build the model, routes, controller, protected some of the existing routes, implemented login/signup forms.

After the user APIs, it was time for the orders API (which also required building a cart and having in place a payment system). I have thought a while about how to implement the cart, and in the philosophy of being stateless I decided that I should implement it via browser _local storage_. I'm still not sure whether I made the correct call, however it seemed logical to me to have the cart items in the user's browser (for users that don't like logging in until they really have to, which in this case would be - actually placing the order), so that they can have their cart items whenever they return to the site, whether logged in or not. For the payments I implemented the PayPal API. I have researched the topic a while, thought about Stripe and other providers, but in the end the decision came mostly because of territory coverage and some other reasons that had nothing to do with coding.

At this point I was already 3.5-4 months into the project and I felt confident enough I will succeed in building this project and that I will finish it relatively quickly. However, what I miscalculated is that building the admin panel (which is designed to administrate products, orders and users), user panel (which also shows user orders and liked products), all that gimmicks like like and share buttons, ratings, would require implementing ton of functionality that would take up a significant amount of time and code. 

Nevertheless, I went ahead and built the administrator section in a simple dashboard fashion, without fancy graphs or plenty of eye-candy (this can always be added later is the shop takes off, and products and orders start piling up).

At this point I realized that I would need to have product archive functionality, that will store snapshots of all product versions. It occurred to me that each product details might be subject to changes during their lifecycle and that there must be a trace what exactly each version contained, and what version each user ordered. I thought a bit about how to implement this and decided to store the entire product data as an archive version. Each time a product is updated, its version automatically gets incremented and the old data is stored as an archived copy. The admin panel has access to the product archive, so basically each product card in the admin panel also displays that product's archived versions. This seems neat to me, as the administrator can easily access this data and see what each user ordered in case of complaints, however I still wonder whether there was a more elegant way to implement this (storing only differential data or something)...

I didn't have to rewrite too much code to implement the new model, controller and routes for the archive functionality, however, together with some issues I had while building the cart, made me become aware of the significance of taking the time to properly think through and plan your algorithms and all the necessary interfaces between them, before you start working on the code. This being my first large project and with ton on stuff I was yet to learn, I could not have foreseen this, however, for the next project I'm planning, I'll definitely know better (which is precisely why I bought a 1.5 square meters whiteboard :-D ).

The last backend functionality I needed to implement was email functionality, which I did using Nodemailer. It is relatively simple to use, has adequate documentation and I didn't have problems implementing this. I adapted some ready email templates that can be found online as I didn't have the time to design new ones, but I'm planning to get back to this and make new ones that will better convey the design and brand of the site.

Finally, the interface needed to take final shape and get all that makeup that modern websites usually have and make it responsive as well. This process was a bit of a struggle as I didn't have any Figma or XD designs to work against, plus everybody has different taste when it comes to... everything. This is where using a framework, library, template would have helped tremendously both in time saving and code, however I do not regret walking this route by foot, as it was a great learning experience, plus I wanted to implement some functionality (such as the alternating product cards, and the card design as a whole) which I couldn't find as a feature of these frontend tools. I spent a good amount of time looking for some ideas and designs, combined some interface concepts that I really liked, did little bit of work in Photoshop and Illustrator and came up with what is now the design of v1 of this project.

In the end, even though I'm aware I could have made certain aspects of this web app better (especially the CSS which I definitely need to clean up, the paypal account is still the development one, so do not order anything yet :-D, etc.), I still am pleased with the end result, considering there were many things I needed to and did learn through building this e-commerce website. I took the effort to make it SEO optimized by making it SSR-ed, and by using slugs for the product URLs among other things. I still need to test this for HTML, CSS and SEO compliance, however I don't expect any significant issues here, just minor attribute tweaking.

I have couple of features I might add before final publishing (visitations counter, search functionality, comments, the dreaded cookies notification etc.), but mostly what was planned is already implemented.

## So, what's the point of this lengthy post? 

Firstly, to introduce myself properly. This is my first post here and I plan to pursue this dev path full-time, so I see this as a perfect opportunity to get in touch with other developers, learn something, share experience and knowledge with others and maybe collaborate on a future project.

Secondly, I see this site as the closest thing to what used to be the forums, and to be perfectly honest I miss many of them that lost significant traction due to users moving to social networks or worse got shut down. In my life I learned and shared an immense number of things thanks to forums and fantastic members, things you literally could not learn elsewhere, get information on things you do not have access to etc., and I feel I need to do my part in preserving that culture.

I didn't want to burden this post with code and algorithms, as this was not the point of this post to begin with, however I'm making the entire code available on [GITHUB](https://github.com/webdynamics-dev/excessive.git). 

I would very much appreciate any suggestions, comments or critics anyone might have towards how I designed and build the code, especially when it comes to securing the app.