This is example eshop. You can add products, edit products, add products to cart and create orders. All is stored in nosql MongoDb. Use MongoDB Compass for working with database.

-utils
    |
    |---db.js

-routes
    |
    |---admin.js
    |---shop.js

-controllers
    |
    |---shop.js

-models
    |
    |---product.js

-views
    |
    |--product-add.js
    |--product-edit.js
    |--product.ejs
    |--shop.ejs
    |
    |---includes
    |       |
    |       |---head.ejs
    |       |---nav.ejs
    |
    |---shop
            |
            |---cart.ejs
            |---orders.ejs

-public
    |
    |---css
        |
        |---main.css
-app.js



models/product.js

const url = 'mongodb+srv://MONGODB_USER:MONGODB_PASSWORD@cluster0-gconm.mongodb.net/MONGODB_DATABASE?retryWrites=true&w=majority';
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;

let _db;

const mongoConnect = (callback) => {
  MongoClient.connect(
    url
  )
    .then(client => {
      console.log('Connected!');
      _db = client.db();
      callback();
    })
    .catch(err => {
      console.log("DB NOT CONNECTED");
      console.log(err);
    });
};

const getDb = () => {
    if (_db) {
        return _db;
    }
    throw 'No db found';
}

exports.mongoConnect = mongoConnect;
exports.db = getDb;



models/product.js

const fs = require('fs');
const path = require('path');
const mongodb = require('mongodb');
const getDb = require('../util/db').db;

class Product {
    constructor(title, description, price, id, userId) {
        this.title = title;
        this.description = description;
        this.price = price;
        this._id = id ? new mongodb.ObjectId(id) : null;
        this.userId = userId;
    }

    save() {
        const db = getDb();
        db.collection('products')
        .insertOne(this)
        .then(res => {
            console.log(res);
        })
        .catch(err => {
            console.log(err);
        });
    }

    //static means that it will be not called on concrete instance of product model, but will return all products
    static fetchAll() {
        const db = getDb();
        return db
        .collection('products')
        .find()
        .toArray()
        .then(products => {
            console.log(products);
            return products;
        })
        .catch(err => {
            console.log(err);
        });
    }

    static fetchById(prodId) {
        const db = getDb();
        return db
        .collection('products')
        .find({ _id: new mongodb.ObjectId(prodId) })
        .next()
        .then(product => {
            return product;
        })
        .catch(err => {
            console.log(err);
        })
    }

    static updateById(prodId, values) {
        const db = getDb();
        db
        .collection('products')
        .updateOne(
            { _id: new mongodb.ObjectId(prodId) }, 
            { $set: values }
        );
    }
}

module.exports = Product;



models/user.js

const mongodb = require('mongodb');
const getDb = require('../util/db').db;

const ObjectId = mongodb.ObjectId;

class User {
    constructor(username, email, cart, id) {
        this.name = username;
        this.email = email;
        this.cart = cart;
        this._id = id;
    }

    save() {
        const db = getDb();
        db.collection('users').insertOne(this);
    }

    addToCart(product) {
        //is product already in cart ?
        const cartProductIndex = this.cart.items.findIndex(cp => {
          return cp.productId.toString() == product._id.toString();
        });
        let newQuantity = 1;
        const updatedCartItems = [...this.cart.items];

        //if it is greater > -1, product is already there
        if (cartProductIndex >= 0) {
          newQuantity = this.cart.items[cartProductIndex].quantity + 1;
          updatedCartItems[cartProductIndex].quantity = newQuantity;
        } else {
          updatedCartItems.push({ 
            productId: new ObjectId(product._id), 
            quantity: newQuantity})
        }

        const updatedCart = { 
          items: updatedCartItems
        };

        const db = getDb();
        return db.collection('users').updateOne(
          {_id: new ObjectId(this._id)},
          { $set: { cart: updatedCart }}
        );
    }

    getCart() {
      const db = getDb();
      const productIds = this.cart.items.map(i => {
        return i.productId;
      });
      return db
        .collection('products')
        .find({ _id: { $in: productIds } })
        .toArray()
        .then(products => {
          return products.map(p => {
            return {
              ...p,
              quantity: this.cart.items.find(i => {
                return i.productId.toString() === p._id.toString();
              }).quantity
            };
          });
        });
    }

    static findById(userId) {
        const db = getDb();
        return db
          .collection('users')
          .findOne({ _id: new ObjectId(userId) })
          .then(user => {
            console.log(user);
            return user;
          })
          .catch(err => {
            console.log(err);
          });
      }
    
      deleteItemFromCart(productId) {
        const updatedCartItems = this.cart.items.filter(item => {
          return item.productId.toString() !== productId.toString();
        })
        const db = getDb();
        return db
          .collection('users')
          .updateOne(
            { _id: new ObjectId(this._id)},
            { $set: { cart: { items: updatedCartItems} } }
          );
      }

      addOrder() {
        const db = getDb();
        return this.getCart().then(products => {
          const order = {
            items: products,
            user: {
              _id: new ObjectId(this._id),
              name: this.name
            }
          };
          return db.collection('orders')
          .insertOne(order);
        })
          .then(result => {
            this.cart = { items: [] };
            return db
              .collection('users')
              .updateOne(
                { _id: new ObjectId(this._id) },
                { $set: { cart: { items:[] } } }
              );
          });
      }

      getOrders() {
        const db = getDb();
        return db.collection('orders')
        .find({'user._id': new ObjectId(this._id)})
        .toArray();
      }
}

module.exports = User;



controllers/shop.js

const Product = require('../models/product');

exports.getAddProduct = (req, res, next) => {
    res.render('product-add', {
        pageTitle: 'Add product',
        path: '/'
    });
}

exports.postAddProduct = (req, res, next) => {
    const product = new Product(
        req.body.title,
        req.body.description, 
        req.body.price, 
        null,
        req.user._id);
    product.save();
    res.redirect('/');
}

exports.getProducts =  (req, res, next) => {
    Product.fetchAll().
        then(products => {
            res.render('shop', {
                products: products,
                pageTitle: 'shop',
                path: '/',
                hasProducts: products.length > 0,
                activeShop: true
            });
        });
}

exports.getProduct = (req, res, next) => {
    Product.fetchById(req.params.productId).
        then(product => {
            res.render('product', {
                product: product,
                pageTitle: 'product'
            });
        });
}

exports.getEditProduct = (req, res, next) => {
    Product.fetchById(req.params.productId).
        then(product => {
            res.render('product-edit', {
                product: product,
                pageTitle: 'product'
            });
        });
}

exports.postUpdateProduct = (req, res, next) => {
    Product.updateById(req.params.productId, req.body);
    res.redirect('/');
}

exports.postCart = (req, res, next) => {
    const prodId = req.body.productId;
    Product.fetchById(prodId)
    .then(product => {
        return req.user.addToCart(product);
    })
    .then(result => {
        console.log(result);
        res.redirect('/cart');
    })
}

exports.getCart = (req, res, next) => {
    req.user
        .getCart()
        .then(products => {
            res.render('shop/cart',{
                path: '/cart',
                pageTitle: 'Your cart',
                products: products
            })
        });
}

exports.postCartDeleteProduct = (req, res, next) => {
    const prodId = req.body.productId;
    req.user
        .deleteItemFromCart(prodId)
        .then(result => {
            res.redirect('/cart');
        })
        .catch(error => {
            console.log(error);
        })
}

exports.postOrder = (req, res, next) => {
    let fetchedCart;
    req.user
        .addOrder()
        .then(result => {
            res.redirect('/orders');
        })
        .catch(error => {
            console.log(error);
        })
}

exports.getOrders = (req, res, next) => {
    req.user
        .getOrders()
        .then(orders => {
            res.render('shop/orders', {
                path: '/orders',
                pageTitle: 'Your Orders',
                orders: orders
            });
        })
        .catch(error => console.log(error));
}



routes/admin.js

const path = require('path');
const express = require('express');
const router = express.Router();
const productsController = require('../controllers/shop');

const products = [];

router.get('/product-add', productsController.getAddProduct);

router.post('/product-add', productsController.postAddProduct);

router.get('/product-edit/:productId', productsController.getEditProduct);

router.post('/product-update/:productId', productsController.postUpdateProduct);

module.exports = router;



routes/shop.js

const path = require('path');
const express = require('express');
const router = express.Router();

const shopController = require('../controllers/shop');

router.get('/', shopController.getProducts);

router.get('/products/:productId', shopController.getProduct);

router.post('/cart', shopController.postCart);

router.get('/cart', shopController.getCart);

router.post('/cart-delete-item', shopController.postCartDeleteProduct);

router.post('/create-order', shopController.postOrder);

router.get('/orders', shopController.getOrders);

module.exports = router;



views/includes/head.ejs

<!DOCTYPE html>
<html>
<head>
    <!-- we are using express.static in app.js to serve static css file from public dir -->
    <link rel="stylesheet" href="/css/main.css">



views/includes/navigation.ejs

<nav>
    <ul>
        <li>
            <a href="/">
                Products
            </a>
        </li>
        <li>
            <a href="/admin/product-add">
                Add product
            </a>
        </li>
        <li>
            <a href="/cart">
                Cart
            </a>
        </li>
        <li>
            <a href="/orders">
                Orders
            </a>
        </li>
    </ul>
</nav>



views/product-add.ejs

<%- include('includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('includes/nav.ejs') %>
    <main>
    <h2>Add product</h2>
    <form method="post" action="/admin/product-add">
        <div>
            <label for="title">
                Title
            </label>
            <input type="text" name="title" />
        </div>    

        <div>
            <label for="description">
                Description
            </label>
            <input type="text" name="description" />    
        </div>

        <div>    
            <label for="price">
                Price
            </label>
            <input type="text" name="price" />    
        </div>
        
        <div>
            <input type="submit" value="Submit" />
        </div>
    </form>
    </main>
</body>



views/product-edit.ejs

<%- include('includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('includes/nav.ejs') %>
    <main>
    <h2><%= product.title %></h2>
        <div class="products">
                <div>
                    <form method="post" action="/admin/product-update/<%= product._id %>">
                        <div>
                            <input type="text" name="description" value="<%= product.description %>" />
                        </div>

                        <div>
                            <input type="text" name="price" value="<%= product.price %>" />
                        </div>

                        <div>
                            <input type="submit" value="save" />
                        </div>
                    </form>
                </div>
        </div>
    </main>        
</body>
</html>



views/404.ejs

<%- include('includes/head.ejs') %>
</head>
<body>
    <%- include('includes/navigation.ejs') %>
    <h1>Page not found</h1>
</body>
</html>



views/shop.ejs

<%- include('includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('includes/nav.ejs') %>
    <main>
    <h2>Products</h2>
        <% if (products.length > 0) { %>
            <div class="products">
                <% products.forEach(function(item) {  %>
                    <div>
                        <h3>
                            <%= item.title %>
                        </h3>

                        <div>
                            <%= item.description %>
                        </div>

                        <div>
                            <%= item.price %>
                        </div>

                        <div class="actions">
                            <a href="/products/<%= item._id %>">Detail</a>
                            <a href="/admin/product-edit/<%= item._id %>">Edit</a>
                            <form action="/cart" method="post">
                                <button class="btn" type="submit">Add to cart</button>
                                <input type="hidden" name="productId" value="<%= item._id %>" />
                            </form>
                        </div>
                    </div>
                <%  }); %>
            </div>    
        <% } %>    
    </main>
</body>
</html>



views/product.ejs

<%- include('includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('includes/nav.ejs') %>
    <main>
    <h2><%= product.title %></h2>
        <div class="products">
                <div>
                    <div>
                        <%= product.description %>
                    </div>

                    <div>
                        <%= product.price %>
                    </div>
                    
                </div>
        </div>   
    </main>     
</body>
</html>



views/shop/cart.ejs

<%- include('../includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('../includes/nav.ejs') %>
    <main>
    <h2>Products</h2>
        <% if (products.length > 0) { %>
            <div class="products">
                <% products.forEach(function(item) {  %>
                    <div>
                        <h3>
                            <%= item.title %>
                        </h3>

                        <div>
                            Quantity: <%= item.quantity %>
                        </div>

                        <div class="actions">
                            <form action="/cart-delete-item" method="post">
                                <button class="btn" type="submit">Delete</button>
                                <input type="hidden" name="productId" value="<%= item._id %>" />
                            </form>
                        </div>
                    </div>
                <%  }); %>
            </div>    

            <div class="actions">
                <form action="/create-order" method="post">
                    <button class="btn" type="submit">Create Order</button>
                </form>
            </div>
        <% } %>    
    </main>
</body>
</html>



views/shop/orders.ejs

<%- include('../includes/head.ejs') %>
<title><%= pageTitle %></title>
</head>

<body>
    <%- include('../includes/nav.ejs') %>
    <main>
    <h2>Orders</h2>
        <% if (orders.length > 0) { %>
            <div class="orders">
                <% orders.forEach(function(order) {  %>
                    <div>
                        <h3>
                            Order <%= order._id %>
                        </h3>

                        <% order.items.forEach(function(item) { %>
                            <div>
                                <%= item.title %>
                                Quantity: <%= item.quantity %>
                            </div>
                        <% }); %>    
                    </div>
                <%  }); %>
            </div>    
        <% } %>    
    </main>
</body>
</html>



app.js

const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();

const shopRoutes = require('./routes/shop');
const adminRoutes = require('./routes/admin');

const mongoConnect = require('./util/db').mongoConnect;
const User = require('./models/user');

//set template engine to EJS
app.set('view engine', 'ejs');
app.set('views', 'views');

//add this to make public folder available to serve static files, like css
app.use(express.static(path.join(__dirname, 'public')));

app.use((req, res, next) => {
    User.findById('5e3ed9cee844e413f1269e18')
    .then(user => {
        req.user = new User(user.name, user.email, user.cart, user._id);
        next();
    })
    .catch(err => console.log(err));
})

app.use(bodyParser.urlencoded({exteneded: false}));
app.use(shopRoutes);
app.use('/admin', adminRoutes);

app.get('/test', (req, res, next) => {
    res.send('<h1>testing</h1>');
});

app.get('/', (req, res, next) => {
    res.send('<h1>hello</h1>');
});


mongoConnect(()  => {
        app.listen(3000);
});