Skip to main content
  1. All Posts/

bestbags-nodejs-ecommerce

eCommerce JavaScript

BestBags

Table of contents

Introduction

A virtual ecommerce website using Node js, Express js, and Mongoose.
NOTE: Please read the RUN section before opening an issue.

Demo

The application is deployed to Heroku and can be accessed through the following link:
BestBags on Heroku
The website resembles a real store and you can add products to your cart and pay for them. If you want to try the checkout process, you can use the dummy card number provided by stripe for testing which is 4242 4242 4242 4242 with any expiration date, CVC, and zip codes. Please DO NOT provide real card number and data.
In order to access the admin panel on “/admin” you need to provide the admin email and password.

Run

To run this application, you have to set your own environmental variables. For security reasons, some variables have been hidden from view and used as environmental variables with the help of dotenv package. Below are the variables that you need to set in order to run the application:

  • MONGO_URI: this is the connection string of your MongoDB Atlas database.
  • SESSION_SECRET: a secret message for the session. You can use any string here.
  • STRIPE_PRIVATE_KEY: the stripe package is used to process payment in the checkout route. To get this, you should set up a stripe account and put your private API key here.
  • GMAIL_EMAIL, GMAIL_PASSWORD: the email and password given to nodemailer to send/receive the email. Please put a real email and password here because you will receive the messages sent from the contact us form on this email.
  • ADMIN_EMAIL, ADMIN_PASSWORD: the email and password used to log into the admin panel using AdminBro. You can put any email and password here.
  • ADMIN_COOKIE_NAME, ADMIN_COOKIE_PASSWORD: the cookie name and password used in the AdminBro authentication method. You can put any strings here.

After you’ve set these environmental variables in the .env file at the root of the project, you need to navigate to the “seedDB” folder and run “node category-seed.js” and “node products-seed.js” to fill your empty MongoDB Atlas database.
Now you can run “npm start” in the terminal and the application should work.

Technology

The application is built with:

  • Node.js version 12.16.3
  • MongoDB version 4.2.0
  • Express version 4.16.1
  • Bootstrap version 4.4.1
  • FontAwesome version 5.13.0
  • Stripe API v3: used for payment in the checkout page
  • Mapbox API: used to show the map in the about us page
  • AdminBro: used and customized to implement the admin panel
  • Nodemailer: used to send emails from the contact us form
  • Passport: used for authentication
  • Express Validator: used for form validation

Features

The application displays a virtual bags store that contains virtual products and contact information.
Users can do the following:

  • Create an account, login or logout
  • Browse available products added by the admin
  • Add products to the shopping cart
  • Delete products from the shopping cart
  • Display the shopping cart
  • To checkout, a user must be logged in
  • Checkout information is processed using stripe and the payment is send to the admin
  • The profile contains all the orders a user has made

Admins can do the following:

  • Login or logout to the admin panel
  • View all the information stored in the database. They can view/add/edit/delete orders, users, products and categories. The cart model cannot be modified by an admin because a cart is either modified by the logged in user before the purchase or deleted after the purchase.

Database

All the models can be found in the models directory created using mongoose.

User Schema:

  • username (String)
  • email (String)
  • password (String)

Category Schema:

  • title (String)
  • slug (String)

Product Schema:

  • productCode (String)
  • title (String)
  • imagePath (String)
  • description (String)
  • price (Number)
  • category (ObjectId – a reference to the category schema)
  • manufacturer (String)
  • available (Boolean)
  • createdAt (Date)

Cart Schema:

  • items: an array of objects, each object contains:
    ~ productId (ObjectId – a reference to the product schema)
    ~ qty (Number)
    ~ price (Number)
    ~ title (String)
    ~ productCode (Number)
  • totalQty (Number)
  • totalCost (Number)
  • user (ObjectId – a reference to the user schema)
  • createdAt

    **The reason for including the title, price, and productCode again in the items object is AdminBro. If we are to write our own admin interface, we can remove them and instead populate a product field using the product id. However, AdminBro doesn’t populate deep levels, so we had to repeat these fields in the items array in order to display them in the admin panel.

  <h3 dir="auto">
    <a rel="nofollow noopener" target="_blank" id="user-content-order-schema" class="anchor" aria-hidden="true" href="#order-schema"></a>Order Schema:
  </h3>
  
  <ul dir="auto">
    <li>
      user (ObjectId &#8211; a reference to the user schema)
    </li>
    <li>
      cart (instead of a reference, we had to structure an object identical to the cart schema because of AdminBro, so we can display the cart&#8217;s contents in the admin interface under each order)
    </li>
    <li>
      address (String)
    </li>
    <li>
      paymentId (String)
    </li>
    <li>
      createdAt (Date)
    </li>
    <li>
      Delivered (Boolean)
    </li>
  </ul>
  
  <h2 dir="auto">
    <a rel="nofollow noopener" target="_blank" id="user-content-colors" class="anchor" aria-hidden="true" href="#colors"></a>Colors
  </h2>
  
  <p>
    Below is the color palette used in this application:
  </p>
  
  <ul dir="auto">
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/217343fc2d52ec83cac05cf4bfd64048008bdc839834e2cc354a9b714babafab/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f3437386261322f3030303030303f746578743d2b"></a> <code>#478ba2</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/2a82139848872b6b811def36bb1cafb8b7543c5bcf9895a9e2b4f19b5dd61870/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f6239643464622f3030303030303f746578743d2b"></a> <code>#b9d4db</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/dbb61b919ef4d3e67be1c2338962b6d5c6a75aa3cc43afba37a3e27378f82838/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f6539373635622f3030303030303f746578743d2b"></a> <code>#e9765b</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/467fea3709bb5575ac556893f767d7c470c6f78150806575e92f6724e9b3d09b/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f6632613439302f3030303030303f746578743d2b"></a> <code>#f2a490</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/4c17e6ae9f5ddbe06220a486133c6f9b5c946e9f62a72cbaedd0d598a26f4a7a/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f6465356236642f3030303030303f746578743d2b"></a> <code>#de5b6d</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/8e91c4ac02df460fa687ac5ddccdb000d624d9fbbac300179be94c645d8dedb6/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f3138613535382f3030303030303f746578743d2b"></a> <code>#18a558</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/e9a5ce197b84f1ec022c6c145a71678dcb4b93b1188faa988fe6829244776bcf/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f6639663766342f3030303030303f746578743d2b"></a> <code>#f9f7f4</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/da281dd79857b95ec7d849a457ee4cebf24a4e2916e8e409871a901806874f2c/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f3230323032302f3030303030303f746578743d2b"></a> <code>#202020</code>
    </li>
    <li>
      <a rel="nofollow noopener" target="_blank" href="https://camo.githubusercontent.com/0f28a766b3f051ac360817b014675e3115bef239cafc6149d74b676ceef41e47/68747470733a2f2f7669612e706c616365686f6c6465722e636f6d2f31352f3437343734372f3030303030303f746578743d2b"></a> <code>#474747</code>
    </li>
  </ul>
  
  <h2 dir="auto">
    <a rel="nofollow noopener" target="_blank" id="user-content-license" class="anchor" aria-hidden="true" href="#license"></a>License
  </h2>
  
  <p>
    <a rel="nofollow noopener" target="_blank" href="http://badges.mit-license.org"></a>
  </p>
  
  <ul dir="auto">
    <li>
      MIT License
    </li>
    <li>
      Copyright 2020 © Maryam Aljanabi
    </li>
  </ul>