Skip to content

sejungkwak/cogito-books

Repository files navigation

Cogito Books

Cogito Books is a fictional B2C online bookstore. The site will be targeted towards people who are interested in reading and buying books. It provides an easy-to-use interface where a user can easily find a book by searching, and make a purchase with or without registration.

The main goal of this project is to demonstrate my full-stack knowledge(HTML, CSS, JavaScript, Python/Django, relational database and Stripe payments) in a real-world context.

Multi device website mockup

View the live project here

Note: The site is for educational purposes only. To simulate a payment, please use a Stripe test card number 4242 4242 4242 4242 with any three-digit CVC and a valid future date.


Table of Contents

User Experience (UX)

Technical Design

Agile methodology

Features

Search Engine Optimisation (SEO)

Business Model

Web Marketing

Technologies Used

Testing

Deployment

Credits


User Experience (UX)

Website Goals

  • To create an online bookstore that inspires users to read books.
  • To allow users to easily find a book and make a purchase.

User Stories

  • Epic: Viewing and Navigation

    ID Story
    #1 As a first-time visitor, I want to know what the shop sells immediately so that I can decide whether I will browse further.
    #2 As a first-time visitor, I want to navigate pages easily so that I can find information I'm looking for.
    #3 As a shopper, I want to know if the shop is trustworthy so that I can make a purchase without any worry.
    #46 As a shopper, I want to view a list of all books so that I can easily select some to purchase.
    #47 As a shopper, I want to quickly identify deals, bestsellers and new releases so that I can easily find interesting books.
    #48 As a shopper, I want to view individual book details so that I can decide whether I want to buy the book.
  • Epic: Registration and User Accounts

    ID Story
    #4 As a site user, I want to sign up so that I can save and view my details.
    #5 As a site user, I want to sign in and sign out of my account with my credentials so that I can keep my account secure.
    #6 As a site user, I want to update my password so that I can keep my account secure.
    #7 As a site user, I want to reset my password so that I can access my account even if I forget my password.
    #8 As a site user, I want to save my delivery information so that I don't have to fill in the form every time I make a purchase.
    #9 As a site user, I want to update my delivery information so that I can keep my details up to date.
    #10 As a site user, I want to have a personalised user profile so that I can view my loyalty points and order history.
    #11 As a site user, I want to add books to my wishlist so that I can purchase them at a later time.
    #12 As a site user, I want to sign up for a newsletter so that I can receive regular updates about new books and offers.
  • Epic: Sorting and Searching

    ID Story
    #13 As a shopper, I want to sort all the available books by publishing date so that I can easily identify newly released books.
    #14 As a shopper, I want to sort sci-fi books by user ratings so that I can easily identify the best rated books in sci-fi.
    #15 As a shopper, I want to search for a book by title so that I can easily find a book I'd like to purchase.
  • Epic: Book Reviews

    ID Story
    #16 As a shopper, I want to view reviews of a book so that I can check what other people think of it.
    #17 As a shopper, I want to add a review so that I can share my thoughts.
    #18 As a shopper, I want to leave a rating without writing a review so that I can leave my opinion anonymously.
    #19 As a shopper, I want to update my review so that I can change any incorrect information.
    #20 As a shopper, I want to remove my review so that I can delete an invalid or irrelevant review.
  • Epic: Purchasing and Checkout

    ID Story
    #21 As a shopper, I want to add books to my basket while viewing multiple books at a time so that I can make my purchase as quickly and easily as possible.
    #22 As a shopper, I want to view items in my basket to be purchased so that I can identify the total cost of my purchase and all items I will receive.
    #23 As a shopper, I want to remove or adjust the quantity of individual items in my basket so that I can easily make changes to my purchase before checkout.
    #24 As a shopper, I want to easily enter my payment information so that I can check out quickly and with little hassle.
    #25 As a shopper, I want to collect loyalty points so that I can use it to purchase books.
    #26 As a shopper, I want to feel my personal and payment information are safe and secure so that I can confidently provide the needed information to make a purchase.
    #27 As a shopper, I want to view an order confirmation after checkout so that I can verify that I haven't made any mistakes.
    #28 As a shopper, I want to receive an email confirmation after checking out so that I can keep it as an invoice of what I've purchased for my records.
  • Epic: Help Centre

    ID Story
    #29 As a shopper, I want to see FAQs so that I don't have to contact the store and wait for them to respond.
    #30 As a shopper, I want to contact the store so that I can receive answers to my queries before purchase.
    #31 As a shopper, I want to receive notification via email the store answers my queries so that I can conveniently check it.
    #32 As a store owner, I want to receive notifications upon a shopper's contact so that I can reply in a timely manner.
  • Epic: Admin and Store Management

    ID Story
    #33 As a store owner, I want to add new products to my store so that I can ensure there is always something of interest to new and existing shoppers.
    #34 As a store owner, I want to update product details such as prices, description, images and so on so that I can keep the product details up to date.
    #35 As a store owner, I want to delete a product so that I can remove items that are no longer for sale.

Design

  • Colour Scheme

    The main colours are black and white to enhance readability. Blue is added to particular elements such as buttons and notifications where information needs to grab the user's attention.

  • Typography

    Montserrat is the main font used throughout the whole website with Sans Serif as the fallback font in case the font isn't imported into the browser correctly. Montserrat has a highly readable body typeface and a variety of weights and styles.

  • Logo

    Logo

  • Favicon

    Favicon

Wireframes

Homepage
Book Category and Details
Basket, Checkout and Order Confirmation
Sign up and Sign in
User Accounts
Help Centre: Contact Us and FAQs

Back To Table of Contents


Technical Design

Database

ElephantSQL was used for the main database.

Entity Relationship Diagram

ER Diagram

Models

  • Books app

    • Category
    • Genre
    • Author
    • Book
    • Review
    • Recommendation
  • Checkout app

    • Order
    • OrderLineItem
  • Helpcentre app

    • UserContact
  • Profile app

    • Profile: inherits the Django user model
    • Wishlist

Back To Table of Contents

Agile methodology

MoSCoW method and story points

GitHub Projects kanban board, Issues and Milestones were used to practise agile methodology. After creating the user stories, I prioritised each story using MoSCoW method and set the points using modified Fibonacci sequence(1, 2, 3, 5, 13) based on complexity, amount of work and repetition.

Iterations

The project was carried out over 5 iterations between the 12th of January and the 28th of January and each iteration lasted 3 days due to the tight schedule. The velocity is 31.6.

The details can be found below:

Back To Table of Contents


Features

Implemented Features

The site features a fully responsive design and contains several e-commerce pages(basket and checkout) as well as book displaying pages(fiction, nonfiction and children's, sale, bestsellers, new releases and book of the month), 3 profile pages(account details, order history and wishlist), 2 admin user pages(add a book and book of the month), django-allauth authentication pages and 5 supporting pages(About us, terms & conditions, privacy policy, contact us and FAQs). The header and footer are identical for all pages. Each user input is validated and feedback is given accordingly.

  • Header

    Header

    • All the header items except profile menus are available to both unregistered and registered users.

    • The header is fixed to the top of the screen even when the user is scrolling down the page to allow easier navigation.

    • The navbar allows the user to quickly navigate to the sections of the store that are of the most interest to them.

    • The navigation menu collapses on small/medium devices less than 992px width to optimise the menu for smaller screen sizes.

      Navigation menu on mobile devices

      Navigation menu on mobile devices

    • The search bar allows a user to search for a book based on a title, publisher, author, ISBN or even keyword from the book description.

  • Footer

    Footer

    • All the footer items are available to both unregistered and registered users.

    • The footer includes links for the following three parts: About us, Help centre and social media page.

    • A newsletter sign up form allows users to subscribe to the store's newsletter.

    • The Facebook link opens in a new tab to allow the user to return to Cogito Books more easily.

      Footer on mobile devices

      Footer on mobile devices

  • Homepage

    Homepage

    • The bestsellers and new releases carousels catch the user's attention.
    • Add to basket buttons allow users to make a purchase conveniently without needing to click multiple times.
  • Book of the month

    Book of the month page

    • Book of the month blog post allows the user to learn a little about a book recommended by the superuser.
    • This can be used to connect with users and encourage return visitors to the store.
    • This also allows for direct marketing of specific books to users.
    • The superuser can upload media files to the content to make it more interesting.
  • Category page

    Category view

    • Each category page displays 16 books on a single page and shows a paginator if exceeded.
    • A user can sort books in a specific order, for example, title, price, rating and publication date.
    • A user can add a book to their basket or wishlist from here.
  • Book details page

    Book detail page

    • The user can open a page for each book. This provides more information about the specific book.
    • The user can also read/write/update/delete a review for the book or just rating scores.
    • The description is truncated to allow users to see all the book details at a glance.
    • The user can also add a book to basket or to their wishlist for future purchases.
  • Wishlist page

    Wishlist

    • This page allows the user to save a list of books they wish to purchase at a later time.
    • This page shows when books are on sale, allowing a user to quickly check when a book they are interested in is available at a discount price.
  • Basket page

    Basket page

    • The basket follows the familiar concept from online shopping.
    • The user can select items to add/remove from/to the basket while browsing the page.
    • At any time the user can view the contents of the basket and increase/decrease the quantity or completely remove an item.
    • The user can see the total of their transaction before delivery costs.
  • Checkout page

    Checkout page

    • This page allows the user to complete the transaction and purchase all selected items from their basket.
    • The user can specify an email address to receive the invoice for this transaction. The default behaviour uses the email address saved in the account details for this account.
    • The user can specify a delivery address to receive the books from this transaction. The default behaviour uses the postal address saved in the account details for this account.
    • The signed in user can collect loyalty points and redeem them with no minimum requirements.
  • Checkout success page

    Checkout success page

    • A unique ID is generated for each completed transaction to allow referencing this transaction at a later time by either the user or the superuser.
    • When a user completes a transaction, a confirmation page displays and an invoice is sent to their email address.
  • Order history page

    Order history page

    • The order history page allows the user to view all previous transactions arranged by most recent.
    • The user can click on the unique ID for the transaction to view more details, including all items purchased in this transaction, the total cost as well as the delivery address used for these books.
  • Account detail page

    Account detail page

    • This page allows the user to add and edit their account details.
    • Default delivery address is pre-populated when the user wants to make a purchase on the site. Their details are automatically added from here to speed up the process.
    • A username can be edited by the user here and is visible to other users when adding book reviews.
    • Users can view their loyalty points here to keep track of how much money they can save on their next transaction.
  • Product management menu page

    Product management menu page

    • This page is only accessible to the superuser and allows the superuser to access the Add a book page and the Add a book of the month blog post feature.
  • Add a book page

    Add a book page

    • The page allows the superuser to add a new book to sell to the shop.
    • A superuser can add a genre if it has not yet been added. The new genre is automatically registered on the navigation menu.
    • A superuser can add an author if it has not yet been added.
    • A superuser can add multiple authors for the book, if required.
  • Add a book of the month page

    Add a book of the month page

    • This page allows the superuser to create a blog post highlighting the book of the month for each month.
    • This blog post allows the superuser to interact with customers on the website.
    • The superuser may choose not to publish the blog post right now and instead publish it later. This allows for the creation of these posts in advance.

Features Left to Implement

  • Bestsellers calculation system It will use the purchase history of the whole store to calculate which books are selling the most over the most recent period and allows the superuser to highlight and promote these books to the users.

  • Bestsellers calculation system It will use the purchase history of the whole store to calculate which books are selling the most over the most recent period and allow the superuser to highlight and promote these books to the users.

  • Better filtering system for the search query The search bar should be better optimised to allow the user to specify the field to search. I.e. searching for “King” but limiting the search for authors should only return results where “King” is part of the author’s name and not where it is a keyword in the description, or part of the publisher’s name.

  • Delivery fee At the moment, the site calculates delivery fee as a flat 10% of the transaction price but I think it would make more sense to calculate a delivery fee based on the destination country - with closer to Ireland resulting in a cheaper delivery fee compared to the flat 10%, while further abroad might be more expensive.

  • Stock By adding a stock value to the database for each book, the superuser can keep track of how many copies of each book are remaining and whether new copies should be ordered.

  • Order management system Currently, a superuser needs to sign in to the admin site to review the orders. It would be better if the admin site was accessible via the main site portal.

Back To Table of Contents


Search Engine Optimisation (SEO)

Keywords

As a part of SEO, keywords were chosen using the following steps: Firstly, write down the site's general topics. Next, brainstorm possible keywords for each topic. Then, enter each keyword in Google search to find a list of short-tail keywords and long-tail phrases. After that, select the best ones based on their relevance, authority and volume using Wordtracker. The Final list of keywords/phrases used for the site is shown in the table below in bold.

Keywords

Sitemap

sitemap.xml was added to the project's root folder to allow search engines to crawl and navigate.

Robots.txt

robots.txt was added to the project's root folder to let search engines know which pages are accessible to web spiders.

HTTP error pages

Custom error pages have been created with 4 internal links(Homepage, Books page, Account page, Contact Us page) to be more helpful to a user and provide guidance.

  • 404 Page not found ( View 404 Page)

    Screenshot of 404 page

  • 403 Permission denied

    Screenshot of 403 page
  • 400 Bad request

    Screenshot of 400 page
  • 500 Sever Error

    Screenshot of 500 page

Back To Table of Contents


Business Model

Cogito Books is a B2C(Business to Consumer) e-commerce application that sells products(books) to individuals. As the target audience is more likely to buy impulsively, the application is focused on a few points below:

  • Create an intuitive interface to make the payment flow as easy as possible: Add to basket buttons are from the landing page and the basket icon is accessible from anywhere.
  • Create a place where the customers can engage: Currently, A book of month is published and users can share their reviews. This can ben expanded to a book club.
  • Create a points based loyalty program to make them return. It is implemented and customers can use loyalty points with no hassle.

Back To Table of Contents


Web Marketing

Social media and email marketing have been utilised for the project.

Facebook business page

For social media marketing, A Facebook page was created and added business information. The page can be found here.

Screenshot of the Facebook business page

Newsletter Signup Form

For email marketing, a subscription section was added in the footer using the mailchimp-marketing package.

Screenshot of the subscription section

Back To Table of Contents


Technologies Used

Languages

Framework

  • Django was used as the main Python framework.
  • Bootstrap was heavily used for styling.

Programs

  • AWS was used to store static and media files.
  • Balsamiq was used to create the wireframes.
  • Canva was used to design the logo and favicon.
  • Chrome DevTools was used to view the site's styling, debug during development and check runtime performance.
  • Diagrams.net was used to create the ERD.
  • ElephantSQL was used to store data.
  • Favicon.io was used to create the favicon.
  • Font Awesome was used for the icons' SVG code.
  • Git was used for version control.
  • GitHub was used to store and deploy the project's code.
  • Gitpod was used to develop and test my code.
  • Google Fonts was used to embed Montserrat.
  • Grammarly was used to check for errors in the README.
  • Heroku was initially used to deploy the project.
  • Render was used to deploy the project.
  • Mailchimp was used to utilise the newsletter sign up functionality.
  • NY Times Books API was used to get a list of books.
  • Privacy Policy Generator was used to create the site's privacy policy.
  • Stripe was used to accept payments.
  • Techsini was used to create the image showing a responsive design for the README.
  • Terms and Conditions Generator was used to create the site's terms and conditions.
  • Visual Studio Code was used to edit my code and create SVG paths from SVG image files.
  • XML-Sitemaps.com was used to generate the sitemap.xml file.

Back To Table of Contents


Testing

Testing details can be found here

Back To Table of Contents


Deployment

Heroku

This project was deployed from GitHub to Heroku using ElephantSQL and AWS. These steps demonstrate how I set up for deployment.

  1. Create a new database instance on ElephantSQL.

  2. On the ElephantSQL dashboard, select the instance I just created.

  3. Copy the value of the URL field.

  4. Go to Heroku and create a new app.

  5. Paste the database URL into the Config Var field.

  6. In the terminal, run the following command: pip3 install dj_database_url==0.5.0 psycopg2

  7. In the terminal, run the following command: pip freeze > requirements.txt

  8. In settings.py, comment out the original DATABASES section and add the new code to connect to the ElephantSQL database:

    # DATABASES = {
    #     'default': {
    #         'ENGINE': 'django.db.backends.sqlite3',
    #         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    #     }
    # }
        
    DATABASES = {
        'default': dj_database_url.parse('my-database-url')
    }
    
  9. In the terminal, run the following command: python3 manage.py showmigrations

  10. Make sure that none of the migrations is checked off.

  11. Migrate my database models to the new database by running the following command: python3 manage.py migrate

  12. Load the fixtures in the following order:

    1. python3 manage.py loaddata categories
    2. python3 manage.py loaddata genres
    3. python3 manage.py loaddata authors
    4. python3 manage.py loaddata books
  13. Create a superuser for the new database: python3 manage.py createsuperuser

  14. Revert to the original database after the migrations.

  15. To confirm the migrations are successful, go to ElephantSQL and select BROWSER on the left hand side menu.

  16. Click the Table queries button and then auth_user.

  17. Click Execute and 1 superuser that I just created returns.

  18. In settings.py, change the database settings as follows:

    if 'DATABASE_URL' in os.environ:
    DATABASES = {
        'default': dj_database_url.parse(os.environ.get('DATABASE_URL'))
    }
    else:
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
            }
        }
    
  19. In the terminal, install gunicorn: pip3 install gunicorn.

  20. Add it to the dependency list: pip3 freeze > requirements.txt.

  21. Create Procfile.

  22. Add the line below to the file. (I input cogito-books at first and got an error H10-App Crashed. The hyphen should be an underscore.)

    web: gunicorn cogito_books.wsgi:application
    
  23. Add DISABLE_COLLECTSTATIC and set it to 1 in the Config Var field on Heroku.

  24. In settings.py, add the Heroku URL to ALLOWED_HOSTS.

  25. Add, commit and push all the changes to Git.

  26. Under the Deploy tab on Heroku, connect to GitHub repository.

  27. Enable automatic deploys for the next time.

  28. For this time, deploy manually by clicking the Deploy Branch button.

  29. In settings.py, change the DEBUG variable to 'DEVELOPMENT' in os.environ.

  30. Add, commit and push it to Git.

  31. Sign in AWS and go to AWS Management Console.

  32. Search for S3.

  33. Select Create bucket.

  34. Enter name, select region, ACLs enabled > Bucket owner preferred for the object ownership section and uncheck Block all public access.

  35. Click the Create bucket button.

  36. Select the bucket I just created.

  37. Go to the Static website hosting and select Use this bucket to host a website and enter index.html and error.html in the document fields.

  38. Go to Permissions and add the configuration to the editor.

    [
        {
            "AllowedHeaders": [
                "Authorization"
            ],
            "AllowedMethods": [
                "GET"
            ],
            "AllowedOrigins": [
                "*"
            ],
            "ExposeHeaders": []
        }
    ]
    
    
  39. Go to Policy Generator.

  40. Select S3 Bucket Policy for the type of policy.

  41. Enter * in Principal, select GetObject for Actions and input ARN(Amazon Resource Name).

  42. Click Add Statement and then Generate Policy.

  43. Copy the policy that popped up and paste it into the editor.

  44. Add /* onto the end of the resource key to allow access to all resources.

  45. Click Save.

  46. For the Access control list (ACL) section, click Edit and enable List for Everyone (public access).

  47. Go to IAM.

  48. Select User Groups from the left hand side menu.

  49. Click the Create group button.

  50. Enter the group name and click the Create group button.

  51. Select Policies from the left hand side menu.

  52. Click the Create policy button.

  53. Select the JSON tab and click Import managed policy.

  54. In the popup window, search for S3 and select AmazonS3FullAccess.

  55. Change the value of the Resource to the following:

    [
        "my_ARN",
        "my_ARN/*",
    ]
    
  56. Click Review Policy.

  57. Give it a name and description and create it.

  58. Go back to User Groups.

  59. Select a group for this project.

  60. Go to the Permissions tab.

  61. open Add permissions and click Attach policies.

  62. Select the policy and click Add permissions.

  63. Select User from the left hand side menu.

  64. Click Add user.

  65. Enter a user name and select Next.

  66. Check off the user and click the buttons until the last step.

  67. Click Download .csv.

  68. Add the credentials from the above steps to Heroku Config Vars.

  69. In the terminal, install the following packages. boto3 and django-storages.

  70. Add django-storages to INSTALLED_APP.

  71. On Heroku, add USE_AWS to Config Vars, set it to True and remove DISABLE_COLLECTSTATIC.

  72. Add a file called custom_storages.py to the project's root folder.

  73. Add the code below:

    from django.conf import settings
    from storages.backends.s3boto3 import S3Boto3Storage
    
    
    class StaticStorage(S3Boto3Storage):
        location = settings.STATICFILES_LOCATION
    
    
    class MediaStorage(S3Boto3Storage):
        location = settings.MEDIAFILES_LOCATION
    
  74. Add AWS configurations to settings.py.

    if 'USE_AWS' in os.environ:
        AWS_S3_OBJECT_PARAMETERS = {
            'Expires': 'Thu, 31 Dec 2099 20:00:00 GMT',
            'CacheControl': 'max-age=94608000',
        }
    
        AWS_STORAGE_BUCKET_NAME = 'cogitobooks'
        AWS_S3_REGION_NAME = 'us-east-1'
        AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
        AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
        AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
    
        STATICFILES_STORAGE = 'custom_storages.StaticStorage'
        STATICFILES_LOCATION = 'static'
        DEFAULT_FILE_STORAGE = 'custom_storages.MediaStorage'
        MEDIAFILES_LOCATION = 'media'
    
        STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{STATICFILES_LOCATION}/'
        MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{MEDIAFILES_LOCATION}/'
    
  75. Add, commit and push all the changes to Git.

  76. Go to AWS S3.

  77. Click Create folder and name it media.

  78. Add all the images used in this project to the folder.

  79. Select Grant public read access to this object(s) and click Next and Upload.

  80. Go to the admin site and check off PRIMARY and VERIFIED for the admin address.

  81. Go to Stripe and create a new webhook endpoint for the deployed version.

  82. Add Signing secret to Config Vars on Heroku.

Making a Local Clone

These steps demonstrate how I cloned my repository to create a local copy on my computer to run the code locally.

  1. Navigate to my GitHub Repository.
  2. Click the Code button above the list of files.
  3. Select HTTPS under Clone. I have chosen this option as it is simpler than SSH.
  4. Click the copy icon on the right side of the URL.
  5. Open the Terminal.
  6. Change the current working directory to the location where I want the cloned directory.
  7. Type git clone and then paste the URL I copied in step 4.
$ git clone https://github.com/sejungkwak/cogito-books.git
  1. Press enter. Messages are displayed in the Terminal to indicate the local clone has been successfully created.

Forking this Repository

These steps demonstrate how to make a copy of this repository on your GitHub account to make changes without affecting this repository or to deploy the site yourself.

  1. Log in to your GitHub account.
  2. Navigate to this repository.
  3. Click the fork button on the top right side of the repository.
  4. You should now have a copy of the original repository in your GitHub account.
  5. You can make a local clone from the copied repository on your computer using the steps demonstrated in Making a Local Clone and/or deploy to Heroku using the steps demonstrated in Heroku.

Note: It is crucial to create a virtual environment to run the project on your local machine to protect other Python projects. I have set up a virtual environment by the steps below:

  1. Head over to the directory and create a virtual environment by typing virtualenv .venv in the terminal.
  2. Type . .venv/bin/activate to activate the virtual environment.
  3. Run pip3 install -r requirements.txt in the terminal to install dependencies that are listed in the requirements.txt file.

Back To Table of Contents


Credits

Code

Content

Acknowledgements

  • My fiancé Ciarán Maher for his support, feedback and proofreading.

Back To Table of Contents