The Wee Norn Iron Box is a snack box service that will allow registered users to choose from a selection of different Northern Irish treats to be posted to them in a 'wee' box.
The image above is a screenshot of the site displayed on different devices using Am I Responsive.
A demo of the project can be found here: The Wee Norn Iron Box
-
- Project Goals
- User Stories
- First Time Visitor
- Registered User
- Superuser
- Design
- Colour Scheme
- Typography
- Imagery
- Wireframes
-
- Existing Features
- Features left to be implemented
-
- Languages
- Frameworks, Libraries and Programs
- Dependencies
-
- Github
- Heroku
- Cloning the Repository
-
- Code
- Content
- Media
- Acknowledgements
The goal of this project is to create a snack box service that will allow registered users to choose from a range of drinks, foods and snacks that are only available in Northern Ireland. The project is aimed at anyone who lives/studies/works abroad or elsewhere in the UK, and misses the taste of home!
Registered users will receive a box containing 6 of their chosen Northern Irish goods all for the price of £10, including fast and free delivery.
- As a First Time Visitor, I want to understand the main purpose of the site on my first visit
- As a First Time Visitor, I want to be able to easily navigate the site
- As a First Time Visitor, I want to be able to easily view/use the site on my smartphone
- As a First Time Visitor, I want to be able to see what products are available to add to a snack box
- As a First Time Visitor, I want to know the snack box price
- As a First Time Visitor, I want to be able to read blog posts
- As a First Time Visitor, I want to be able to easily register for an account
- As a First Time Visitor, I want to read reviews from other users
- As a First Time Visitor, I want to be able to follow the company on social media platforms
- As a First Time Visitor, I want to be able to contact the company with any queries I might have
- As a Registered User, I want to be able to easily login and logout of my account
- As a Registered User, I want to be able to easily add and remove items from my box
- As a Registered User, I want to be able to easily purchase my box
- As a Registered User, I want to receive an email confirming my purchase
- As a Registered User, I want to be able to easily update my delivery details in my profile
- As a Registered User, I want to be able to view my order history
- As a Registered User, I want to be able to easily submit blog posts
- As a Registered User, I want to be able to easily edit or delete any blog posts I've submitted
- As a Registered User, I want to be able to comment on other blog posts
- As a Registered User, I want to be able to leave a review on the site to let others know about my experience
- As a Site Owner/Superuser, I want to be able to add new products
- As a Site Owner/Superuser, I want to be able to edit and delete products
- As a Site Owner/Superuser, I want to be able to manage user reviews
- As a Site Owner/Superuser, I want to be able to view and manage all blog posts
- As a Site Owner/Superuser, I want to be able to access the admin panel to view registered users order details so I know what products to add to their box
The overall design of this project is simple and easy to follow, using block shapes with sharp edges and defined borders to display most of the content, mimicking that of a box.
Colour palette generated using coolors.co
The colour palette for this project is based on the colours of the Harland and Wolff cranes in Belfast, Northern Ireland.
#161616
:- Used as the background colour for the navbar and footer as well as the colour for text and buttons
#A30000
:- Used as the hover colour for buttons
#FF9F1C
:- Used as the main background colour across all pages
#FFFFFF
:- Used as the background colour for page headings and cards
Throughout the site, I used two different fonts from Google Fonts. These were Anton with the suggested pairing of Roboto.
The Anton font was used for all main headings on the site and as the font for the logo text, with Roboto being used for all other text.
The images used for this project are product images sourced from a variety of different websites. As this project is for educational purposes, I have credited the websites at the bottom of this document in the credits section. The product images used are of well known Northern Irish/Irish brands including Tayto and Maine Lemonade.
I designed a simple logo for the site using Affinity Photo. The logo is made up of an outline of the map of Northern Ireland and some text with the name of the site - "The Wee Norn Iron Box". I then downloaded a PSD box mock-up from Free Pik and added the logo to the box to use on the landing page. The outline of the map of Northern Ireland is also used for site favicon.
I also used Affinity Photo to create a simple No Image Available image that will display if there isn't an image available for a product.
The wireframes for my site were created using Balsamiq. I created wireframes for mobile, tablet and desktop devices.
Links to the wireframes can be found below. Each link contains the wireframes for mobile, tablet and desktop devices:
The final design of the site loosely follows the design of the wireframes. Rather than displaying the product descriptions with the product image in the same card, I decided to display the description when the user hovers over the product image. I also added a blog app as a suggested feature by my mentor later in the development process.
- Home Page
- Products Page
- Add/Edit/Delete Products (Superuser Only)
- Box Contents
- User Profile
- Add Review
- Login/Sign Up
SQLite3 was used in development as part of the Django framework and Heroku Postgres was used for Production. The models used in the project can be found below:
DB Diagram created using dbdiagram.io to show the relationships between models
Home App:
Review Model
Field | Field Type | Field Options |
---|---|---|
title | CharField | max_length=50, null=True, blank=True |
review | TextField | null=True, blank=True |
posted_by | ForeignKey | User, on_delete=models.CASCADE |
rating | IntegerField | default=0, validators=[MinValueValidator(1),MaxValueValidator(5)] |
Products App:
Category Model
Field | Field Type | Field Options |
---|---|---|
name | CharField | max_length=200 |
Product Model
Field | Field Type | Field Options |
---|---|---|
name | CharField | max_length=254, null=True |
description | TextField | null=True, blank=True |
brand | CharField | max_length=254, null=True, blank=True |
category | ForeignKey | 'Category', null=True, blank=True, on_delete=models.SET_NULL |
size | CharField | max_length=25, null=True, blank=True |
image | ImageField | null=True, blank=True |
Checkout App:
Order Model
Field | Field Type | Field Options |
---|---|---|
order_number | CharField | max_length=32, null=False, editable=False |
user_profile | ForeignKey | UserProfile, on_delete=models.SET_NULL, null=True, blank=False, related_name='orders' |
full_name | CharField | max_length=80, null=False, blank=False |
EmailField | max_length=254, null=False, blank=False | |
contact_number | CharField | max_length=20, null=True, blank=True |
address_line_1 | CharField | max_length=80, null=False, blank=False |
address_line_2 | CharField | max_length=80, null=False, blank=False |
town_or_city | CharField | max_length=80, null=True, blank=True |
county | CharField | max_length=80, null=True, blank=True |
postcode | CharField | max_length=20, null=False, blank=False |
country | CountryField | blank_label="Country *", null=False, blank=False |
date | DateTimeField | auto_now_add=True |
original_box | TextField | null=False, blank=False, default='' |
stripe_pid | CharField | max_length=254, null=False, blank=False, default='' |
Box Items Model
Field | Field Type | Field Options |
---|---|---|
order | ForeignKey | Order, null=False, blank=False, on_delete=models.CASCADE, related_name="boxitems" |
product | ForeignKey | Product, null=False, blank=False, on_delete=models.CASCADE |
Blog App:
Post Model
Field | Field Type | Field Options |
---|---|---|
title | CharField | max_length=254, null=False, blank=False |
post | TextField | null=False, blank=False |
posted_by | ForeignKey | User, on_delete=models.CASCADE |
date_posted | DateTimeField | auto_now_add=True |
status | BooleanField | choices=STATUS, default=1 |
Comment Model
Field | Field Type | Field Options |
---|---|---|
comment | TextField | null=False, blank=False |
posted_by | ForeignKey | User, on_delete=models.CASCADE |
date_commented | DateTimeField | auto_now_add=True |
post | ForeignKey | Post, on_delete=models.CASCADE, related_name="comments" |
- Responsive on all devices with a mobile-first design using Bootstrap
- An easy to use navigation bar located at the top of every page with a toggle button to trigger the nav on mobile devices
- A home page with an about section that explains the purpose of the site
- Login, Log Out and Sign Up functionality
- Add, Edit and Delete functionality for superusers
- A reviews section on the home page that displays reviews left by users and allows logged in users to leave their own review
- A products page with a search bar and category filters
- Product descriptions that display when the user hovers over the product card
- A box page to allow the user to see the contents of their box before they order
- A profile page that displays previous orders and a saved delivery address for future orders as well as blog post drafts
- A checkout page that allows the user to purchase their box using Stripe payments
- A blog page that displays blog posts and allows users to create their own posts as well as comment on other posts
- A footer located on every page with links to social media pages
- Toasts to let the user know when they've successfully completed an action or to let them know if there was a error completing an action
In future releases of this project and as I continue to progress as a developer, I would like to add some additional features to improve the users overall experience:
-
Subscription Payment Option:
- I initially wanted to make this project a subscription box service but due to work commitments and time restraints, I opted for a single payment service to meet the project requirements
- In future, I would like to try adding the stripe subscription payments again as this feature would allow users to have the option to receive a box every month rather than having to log on each time they wish to purchase one
- Along with this, I would also like to give users the option to pause or stop their subscription at any time
-
Multiple Payment Options:
- This feature would give users various options to pay for their box or subscription using Apple Pay or Google Pay
-
Additional Account Options:
- I would like to give the user the option to create an account by logging in with one of their social accounts such as Facebook or Google
- I would also like to give the user the option to delete their account if they no longer wish to use the service
- Affinity Photo
- Affinity Photo was used to design a simple logo for the site and to add the logo to a box mock-up PSD
- AWS Amazon S3
- Amazon S3 (Amazon Simple Storage Service) was used to store static and media files used in the project
- Balsamiq
- Balsamiq was used to create the wireframes for desktop, tablet and mobile during the design process
- Bootstrap
- Bootstrap v5.0 was used to give the site a simple, responsive layout and to also add various Bootstrap components and utilities
- Django
- Django was the web framework used to build the project
- Djecrety
- Djecrety was used generate a secret key
- Font Awesome
- Font Awesome was used to add various icons throughout the site
- Google Fonts
- Git
- Git was used for version control by utilising the terminal in VS Code to commit to Git and push to GitHub. Git was also used to create branches to test new features before merging with the master branch
- GitHub
- GitHub was used to store the project code that was pushed from VS Code
- Heroku
- Heroku is a cloud platform that was used to deploy and run the application from the GitHub repository
- Ngrok
- Ngrok was used to setup an online tunnel to locally test the webhook endpoint in Stripe
- Stripe
- Stripe was used to integrate online payment processing
- VS Code
- Visual Studio Code was the editor used to code the project
- django-allauth
- Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication
- Pillow
- Python imaging library
- Django Countries
- A Django application that provides country choices for use with forms, flag icons static files, and a country field for models
- Django Crispy Forms
- The best way to have Django DRY forms. Build programmatic reusable layouts out of components, having full control of the rendered HTML without writing HTML in templates
- Crispy Bootstrap 5
- Bootstrap5 template pack for django-crispy-forms
- Stripe
- A Python library for Stripe’s API
- dj-stripe
- dj-stripe implements all of the Stripe models, for Django
- dj_database_url
- This simple Django utility allows you to utilize the 12factor inspired DATABASE_URL environment variable to configure your Django application
- psycopg2-binary
- Psycopg is the most popular PostgreSQL database adapter for the Python programming language
- gunicorn
- Gunicorn ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX
- boto3
- Use the AWS SDK for Python (Boto3) to create, configure, and manage AWS services, such as Amazon Elastic Compute Cloud (Amazon EC2) and Amazon Simple Storage Service (Amazon S3)
- django-storages
- A collection of custom storage backends for Django
Further Testing information can be found in a separate document: TESTING.md
This project was developed on macOS using VS Code, with Git and GitHub used for version control. The project is hosted on Heroku, and all static and media files are stored on AWS Amazon S3.
To clone the repository and make a local copy on your computer, follow these steps:
- Open GitHub and locate the GitHub repository: https://github.com/KirstChat/the-wee-norn-iron-box
- Under the repository name, click "Code" and copy the link to clone the repository using "HTTPS"
- After copying the link, open a terminal on your computer - this step can also be done in the terminal in your preferred IDE or Code Editor
- Change the current working directory to the location where you want the cloned directory to be saved
- Type
git clone
, and then paste the URL: https://github.com/KirstChat/the-wee-norn-iron-box.git - Press Enter to create a local clone
- Create a env.py file to store environment variables
- Add the env.py file and the virtual environment folder ("venv") to a ".gitignore" file to ensure this information isn't pushed to the repository on GitHub
- Before installing any required dependencies, create a virtual environment - this will ensure that packages installed are only installed in the virtual environment folder:
python3 -m venv venv
- Run the following command to ensure you are installing packages in the virtual environment and not on your local drive:
source ./venv/bin/activate
- Install the required dependencies from the "requirements.txt" file to run the repository locally:
pip3 install requirements.txt
- Run the app from your local IDE or Code Editor by running the following command in the terminal:
python3 manage.py runserver
This project was coded in VS Code and pushed to GitHub using the following steps:
- Create a new folder in your preferred area in your local drive
- Open the folder in VS Code to start creating files
- Open source control in VS Code and select "Publish to GitHub"
- If prompted, sign into GitHub to connect your account to VS Code if you haven't done so already
- In source control, select "Publish to GitHub"
- Give your repository a name and select "Publish to GitHub Public Repository"
- After the repository is successfully published to GitHub, you can use git bash to add, commit and push any changes to the GitHub repository
- To stage a file to commit, use
git add
and the name of the file you want to commit or alternatively, usegit add .
to add all files to the staging area - After adding a file to commit, use
git commit -m "add commit message here"
to specify what changes you have made to that file - After committing a file, use
git push
to push all staged changes to the GitHub repository
The following steps were used to host the project on Heroku:
- Before creating a Heroku app, open the repository in VS Code and create a requirements file that lists all the applications and dependencies required to run the application:
pip3 freeze --local > requirements.txt
- Create a Heroku specific file called a Procfile - this is what Heroku looks for to know which file runs the app and how to run it:
web: gunicorn the_wee_norn_iron_box:application
- Open Heroku and login to your account or sign up for an account if you don't already have one
- Open the dashboard and select "New" to create a new app
- Name the app and set the region to Europe
- Open the resources tab and add
heroku-postgresql
to the add-ons - Open the settings tab and open "Reveal Config Vars"
- Add the environment variables from the env.py file:
KEY | VALUE |
---|---|
AWS_ACCESS_KEY_ID | YOUR_AWS_ACCESS_KEY_ID |
AWS_SECRET_ACCESS_KEY | YOUR_AWS_SECRET_ACCESS_KEY |
DATABASE_URL | YOUR_DATABASE_URL |
EMAIL_HOST_PASS | YOUR_EMAIL_HOST_PASS |
EMAIL_HOST_USER | YOUR_EMAIL_HOST_USER |
SECRET_KEY | YOUR_SECRET_KEY |
STRIPE_PUBLIC_KEY | YOUR_STRIPE_PUBLIC_KEY |
STRIPE_SECRET_KEY | YOUR_STRIPE_SECRET_KEY |
STRIPE_WEBHOOK_SECRET | YOUR_STRIPE_WEBHOOK_SECRET |
USE_AWS | True |
- Temporarily add the DATABASE_URL to settings.py:
DATABASES = {
'default': dj_database_url.parse('Postgres database URL')
}
- Migrate the database models to the Postgres database using
python3 manage.py migrate
- Load the data fixtures starting with categories and then products using
python3 manage.py loaddata <fixture_name>
- You can create fixtures by using the following command:
python3 manage.py dumpdata --app_name.model_name --indent 2 > fixtures_name.json
- Create a superuser for the Postgres database to access the admin panel using
python3 manage.py createsuperuser
- Remove the Postgres database URL from settings.py as this cannot be deployed to GitHub for security reasons
- To deploy the app from GitHub, open the deploy tab and change the deployment method to GitHub
- Connect to your GitHub account and search for the name of the repository to connect to
- Once connected, "Enable Automatic Deployments" and select the "Master" or "Main" branch to deploy
- Click the "Deploy Branch" button to deploy the app to Heroku
The following steps were used to store static files and media files in an Amazon S3 Bucket:
- Login in to your AWS account or create an account if you don't already have one
- Click on My Account and open the AWS Management Console
- Search for S3 in services and create a new bucket
- Give the bucket a name, set the region closest to you and uncheck "Block all Public Access"
- Open the new bucket and enable static website hosting located at the bottom of the page
- Open the permissions tab and edit the CORS configuration at the bottom of the page to set up the required access between the heroku app and the bucket:
[
{
"AllowedHeaders": [
"Authorization"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
- Open Bucket Policy on the permissions tab and open the policy generator
- Set the policy type to "S3 Bucket Policy", the principal to "*", the action to "GetObject" and add the ARN which can be found on the Bucket Policy Editor page
- Add the statement and then generate the policy
- Copy and paste the generated policy into the Bucket Policy Editor, adding a "/*" to the end of the resource key
-
- The Bootstrap Documentation was used to add different components to the project including a Navbar, Toasts and Cards, as well as to add various Bootstrap classes to style different elements.
-
Code Institute Full Stack Frameworks Boutique Ado Project
- The Boutique Ado project walkthrough from the Code Institute Full Stack Development course was used as a guide to help build this project, particularly the section on creating Stripe webhooks.
-
- CSS linear-gradient was used to add a gradient background to the card overlay for the cards used in the products app.
-
- The Django Documentation was used to create form choices, return a full URL path with a string query and to check the length of a dictionary in the template as well as how to use various other filters in the templates.
-
- This piece of code from Stack Overflow was used to initialise toasts within Bootstrap 5 using vanilla JavaScript instead of jQuery as Bootstrap 5 no longer relies on jQuery.
-
- This code was used to check the url path to display box contents when the user is on the products page but not when the user is on the view box page.
-
- This code was used to set the widget for ratings as radio buttons.
-
- This code from Stack Overflow was used to add active classes to the navbar links to show the user which page they are currently viewing.
-
- This command was used to indent the products and categories datadump to make it easier for users to read.
-
Bootstrap Carousel in for loop
- This code from Stack Overflow was used to add a Bootstrap Carousel with a for loop to display reviews on the home page.
-
- This tutorial was used as a guide to add a blog application to the project to allow users and superusers to create blog posts.
-
- This tutorial was used as a guide to add comments to blog posts.
-
- This code from css-tricks was used to add additional media queries for devices in landscape.
-
- This code from stack overflow was used to add a custom favicon to django administration site.
All product descriptions and sizes were taken the following sites:
Baked Goods
- All Irwin's Product Descriptions from Irwin's Bakery
- Genesis Crafty Wheaten Bread Description from Hungry Expats
- Ormo Potato Farls Description from Hungry Expats
- Ormo Sodas Description from Sainsburys
- Sunblest Veda Bread Description from Appy Shop
Snacks
- All Tayto Crisp Descriptions from Tayto
Drinks
- All Dale Farm Sukie Juice Descriptions form Appy Shop
- Club Orange Description from Hungry Expats
- Club Rock Shandy Description from Asda
- Club Lemon Description from Asda
- Maine Cloudy Lime Description from Appy Shop
- Maine Pineappleade Description from Appy Shop
- Maine Bubblegum Description from Asda
- Maine Attaboy Description from Maine
As this project is for educational purposes, the images included in the project have been sourced form a variety of websites as it was difficult to find free to use images of the products I wanted to feature. Links to these websites can be found below:
Baked Goods
- All Irwin's Product Images from Irwin's
- Genesis Wheaten Bread Product Image from Sainsburys
- Ormo Potato Farls Product Image from Hungry Expats
- Ormo Sodas Product Image from Sainsburys
- Sunblest Veda Bread Product Image Appy Shop
Snacks
- All Tayto Crisps Product Images from Tayto
Drinks
- All Dale Farm Sukie Juice Product Images from Appy Shop
- BPM Focus Energy Drink Product Image from Appy Shop
- Club Orange Product Image from Hungry Expats
- Club Rock Shandy Product Image from Amazon
- Club Lemon Product Image from Amazon
- Maine Cloudy Lime Product Image from Appy Shop
- Maine Pineappleade Product Image from Appy Shop
- Maine Bubblegum Product Image from Amazon
- Maine Attaboy Product Image from Facebook
Other Images
- Northern Ireland Map Outline used for the Logo Clean PNG
- Box Mock-Up used on the Home Page Free Pik
- Ulster Fry used on Products Page The Culture Trip
-
A huge thank you to my mentor Spencer Barriball for all his advice and feedback throughout this project - you've been incredible as always!
-
Thanks to the Slack community for being the most supportive and fantastic group of people.