This is a website for baking recipes of bread, cakes, and biscuits. I create this for Milestone Project 3 (Python and Data-Centric Development), Full Stack Software Development in Code Institute, Ireland. It is a mobile-first & responsive website and the link to the website is available HERE.
This is a website for people who simply love baking, or even just beginning to be interested in baking. People, who would like to see someoneβs recipes for new ideas and/or to share their own recipes with other people, can do both on this website. The website is designed to be obvious its purpose for first-time users. Everything is laid out simply and navigated quite easily so users can adapt to the website fairly quickly, and that makes users keep coming back to the website. All the recipes are visible to any users so they do not need to create an account if they just would like to see recipes. If users would like to create and post their recipes, then they need to create an account but the process of creating an account is very simple. Some users may want to buy new baking items so there is a Shop page where uses can look at some items and purchase them on the seller's website. There is a function to subscribe to a newsletter to get engaged in whatβs happening in baking and the community.
I am the owner of the website. The primary goal of the website is to provide a platform that users can see baking recipes and/or share their recipes without any hassles. There is a Shop page where some baking items are listed (affiliate) so in case users find something interesting, they can access the seller's website for more details and can also purchase them. I can get a commission from the seller for any items being sold through my website and this is also one of the goals. I would like to collect their e-mail address for newsletters to expand the community for further business opportunities.
The website is designed for those who love baking, and who are interested in baking. People who have been baking might want to share their knowledge with other people as it gives them great feeling and motivation, so by following very simple registration steps, they can create an account and post their recipes in a well-structured format. People who have less experience in baking and would just like to see recipes, they can do it simply by visiting the website where all the recipes are shown by posted date, or they can see them by category (e.g bread, cake, biscuit) on different pages. There is a search function on the website so they can search for specific recipes by a keyword(s). To see recipes, users do not need to register so it is hassle-free. There is a shop page that has some baking items in an affiliate style so in case users would like to purchase something, they can do it by clicking the link and it leads users to the sellers website.Β The design of the website is meaningful and simple so that the purpose of the website is very clear for first-time users, and they can easily adapt to the website. This also applies to all the functions to create, post, edit and delete recipes for regular users. The ownerβs main goal is to provide a baking recipe platform that is easy to use whether they are first-time or returning users, and this is the key to grow the community for further business opportunities. To achieve this, the website is designed and created by users first concept.
All the functions on the tables below are minimum requirements on the website to achieve the current user's and owner's goals. (On a scale of 1 [least] - 5 [most])
Opportunity | Importance | Viability / Feasibility |
---|---|---|
Register | 5 | 5 |
Login / Log out | 5 | 5 |
Create / Edit / Delete Recipes | 5 | 4 |
Search Recipes By Keywords | 4 | 5 |
Show Recipes By Category | 4 | 5 |
Shop (Affiliate) | 4 | 5 |
Responsiveness | 4 | 5 |
Subscribe To Newsletter | 4 | 4 |
Manage Recipe Category (Admin only) | 3 | 5 |
Page 404 | 3 | 4 |
Below are the additional functions that can improve the website, however, these are not mandatory to achieve the current user's and owner's goals. Some are not implemented due to a lack of my current skills & knowledge and some due to a lack of time.
Opportunity | Importance | Viability / Feasibility |
---|---|---|
Resetting Password When Users Forget It | 4 | 2 |
Upload Image For Each Recipe | 4 | 2 |
Pagination | 3 | 3 |
Review By Other Users | 3 | 3 |
βLikeβ Reaction By Other Users | 3 | 2 |
Note:
During the project, decide to add pagination as it makes the website much neater so it is implemented in the current project
To achieve user and ownerβs goals, below are the minimum features to be included in this project. Also, CRUD (Create, Read, Update, and Delete) functions are required for this project so these are implemented as a part of essential features.
- Simple design Home page that first-time users can recognise the purpose of the website easily. All the recipes are shown on Home page (R)
- Categories (Bread, Cake and Biscuit) pages where users can see recipes by the categories (R)
- Shop page where users can see some baking items linked to the sellerβs website
- Register page where users can create an account to create, post and edit recipes
- Login page where users can log in to the website
- Logout function that users can log out the website
- Profile page where users can see all their recipes and access to create, post, edit and delete recipes
- Create Recipe page where users can create and post their recipes (C)
- Edit Recipe page where users can edit their recipes (U)
- Delete Recipe function that users can delete their recipes (D)
- Manage Category page and functions that only admin user (owner) can create, edit and delete categories (C & U & D)
- Search by a keyword(s) function that users can search for specific recipes
- Subscribe to newsletter function to collect users e-mail addresses
- 404 page that appears for invalid URL and takes users back to Home page of the website safely
Note:
Initially, only 3 fixed categories are planned for recipes, however as the project is created, discover that a newly created category can be implemented on the website by using loop so categories are not limited. (e.g. If the admin decides to create a new category called "Birthday", it can be implemented to the website automatically)
β Front-end β
The website consists of a Home page with 13 other core pages.
-
Home (
index.html
)
The main page of the website. There is a logo, navigation bar to Categories, Shop, Register & Login pages, a title and a hero image. All the summary of recipes are contained and users can access a full Recipe page. There is a footer with a form to subscribe to newsletter and some social icons -
Search Result (
search.html
)
The page where users can see recipes by search and access a full Recipe page. The same navigation bar and footer are used as Home *Idea of having this page comes up during the project -
Categories (
categories_<category_name>.html
)
The pages where users can see recipes by category and access a full Recipe page. The same navigation bar and footer are used as Home -
Recipe (
recipe.html
)
The page where a full recipe is shown individually. The same navigation bar and footer are used as Home -
Shop (
shop.html
)
The page where users can see some baking items and purchase them on the seller's website. The same navigation bar and footer are used as Home -
Register (
register.html
)
The page where users can create an account. Once users create an account successfully, they will be led to Profile page. The navigation bar is different to Home page, in which users can go back to Home page by clicking Uncle Jam's icon, and there is no footer -
Login (
login.html
)
The page where users who have an account can log in to the website. Once users log in successfully, they will be led to Profile page. The navigation bar is different to Home page, in which users can go back to Home page by clicking Uncle Jam's icon, and there is no footer -
Profile (
profile.html
)
The page where users will be led when they create an account or log in. Users see all of their recipes with an option to edit/delete. Users can access to Edit Recipe page and Delete Recipe function by clicking a button on the recipe. There is an option to create a new recipe from this page by clicking a button and that leads to Create Recipe page. The same navigation bar and footer are used as Home but there is a Logout function instead of Register and Login. There is also a link to Profile page on the navigation bar -
Create Recipe (
create_recipe.html
)
The page where users can create and post recipes. There is no link on the navigation bar and it can only be accessed by clicking a Create Recipe button on Profile page. The page style is the same as Register | Login, and users can go back to Profile page by clicking Gingerbread man icon or cancel button -
Edit Recipe (
edit_recipe.html
)
The page where users can edit recipes. There is no link on the navigation bar and it can only be accessed by clicking an Edit button on Profile page. The page style is the same as Register | Login, and users can go back to Profile page by clicking Gingerbread man icon or cancel button -
Manage Category (
manage_category.html
)
The page where only admin user (owner) can access to create and edit category pages as well as to delete categories. Only admin user can have an access to this page by a navigation link that appears on Profile page for admin. The page style is the same as Home -
Create Category (
create_category.html
)
The page where only admin user (owner) can create categories. The page style is the same as Register | Login, and admin user can go back to Manage Category page by clicking Tools icon or cancel button -
Edit Category (
edit_category.html
)
The page where only admin user (owner) can edit categories. The page style is the same as Register | Login, and admin user can go back to Manage Category page by clicking Tools icon or cancel button -
Page 404 (
page_404.html
)
The page that informs users the page not found and takes them back to Home page safely. The page style is the same as Register | Login.
Summary of recipes and full recipes are accessible by any users. Summary of recipes are available on Home and Categories pages and full recipes are available on Recipe page.
Below is the chart of the website to show the core relationships between the pages. (Most of the pages are linked to each other subject to permission)
β Back-end β
Users must have an account to create recipes so there is a users collection that has username and password as keys of the data. username in users collections is linked with the username in recipes collection because users who have an account can only create a recipe and they create a recipe in their own account. Same principle as username in users collection that users can only create a recipe for the categories available in a categories collection so it is liked with category_name in recipes collection. Categories in categories collection are editable by admin so it is created as an independent collection. Data in subscription collection is independent data for newsletters because users who do not have an account can also subscribe to it if they wish to do. The data in all the collections are retrievable and can be identified by the key or unique id of the object.
Below is the chart of the database to show the collections and their relationships.
Note:
On the subscription collection, subs_name is listed but the subscribe function collects e-mail address only
It is a mobile-first website because people usually bake with a recipe so a good mobile-first design helps users whose main purpose is seeing recipes. For users whose main purpose is creating and posting recipes, the form is also well designed on both mobile and desktop sizes. There are wireframes of mobile and desktop sizes for all the core pages of the website.
Note:
Small design amendments during the project. Some pages have a heading section only
β Colour β
As this is a baking recipes website, Cafe Noir (#493323) is used for the main colour of the website. It is used as it is on some headings, texts as well as the navigation bar, footer, and slightly transparent colour is used for some background. Linen (#FBEADE) and Apricot (#FFD5B7) are used for some text and background when it needs contrast. Mango Tango (#FF7C3E) and Flame (#E84610) are used when it needs an accent on the website such as See Recipe button, flash messages and hover effect.
β Typography β
Amatic SC is used for the main heading βUncle Jamβs Baking Recipesβ (h1) and headings of other pages (h2) because this handwritten type of font links with recipes (hand made) very well.
Balsamiq Sans, which is also another type of handwritten font, is used for menu and other headings (h3 - h6) as it matches the image of the website well.
Nunito, which is Sans Serif type font, is used for texts on the body to give users maximum readability.
This project contains both front-end and back-end so well-structured planning is required to do the work efficiently. Below is a summary of the plans.
- Creating Database in MongoDB
- Installing necessary Python frameworks, creating a Python file for the app and testing functions
- Deploying the website in Heroku
- Connecting Database and App
- Creating parent HTML template with common sections (e.g. header & footer)
- Creating Register, Login, Profile pages
- Creating Create, Edit recipe pages
- Creating Create, Edit category pages
- Creating Categories recipe pages
- Creating an individual Recipe page
- Creating Shop page
- Creating 404 page
Updating README.md and some testing is also done during the above process
- Create with HTML5, CSS3 (with Material Design for Bootstrap), JavaScript, Python (Flask), MongoDB (Atlas)
- It consists of 1 base html file and 14 other html files
- Modal for "Create Recipe" instructions and confirmation for "Delete" function
- All the features planned on scope plane and Pagination
-
Resetting Password When Users Forget It: To achieve this, an e-mail address is probably required for creating an account. The current primary purpose of the website is to provide easy access to the platform so do not ask e-mail address to create an account. In addition, do not know how to implement this with my current skills, decide to leave this out
-
Upload Image For Each Recipe: Image data cannot be stored in MongoDB so this is not possible with the current project however, having image for recipes is achieved by using image URL
-
Review By Other Users: Do not know how to achieve this with my current skill and do not have time to learn so decide to leave this out
-
βLikeβ Reaction By Other Users: Do not know how to achieve this with my current skill and do not have time to learn so decide to leave this out
-
Customise Pagination Page Display: Manage to do pagination as it is essential to make the website neat, however, do not know how to customise pagination page display (e.g. When there are more recipes, it will show page 1, 2, 3, 4, 5, 6, 7...) and do not have time to look into details so decide to leave as it is
-
Error Pages: Only one type of error page (404) is set up for the project. Ideally, users should be directed to a specific error page depending on the type of the error, however, do not have time to implement this so leave this out
-
Posted Date and Updated Date: On recipe summary pages, recipes are shown by the posted date and there is a posted date on the summary of recipes. The function works fine however, when users edit recipe, the posted date is updated so it looks as if they are posted on that date. For any edited recipes, there should be an updated date other than the original posted date, but this is not critical for the current project and do not have time to work on this, decide to leave this out
- HTML5 for markup
- CSS3 for style
- Material Design for Bootstrap 5 & 4 (an open-source toolkit based on Bootstrap for developing Material Design) for the mainframe of the website
- JavaScript for interaction
- Python3 as a backend programming language
- Flask (a micro web framework written in Python) as the main framework of Python
- MongoDB Atlas as database
- Google Fonts for fonts
- Font Awesome for icons
- Gitpod as Integrated Development Environment (IDE)
- Git for local version control, keeping the files & documents
- GitHub for online version control and keeping the files & documents
- Heroku for deploying the website
- Code Institute Course Materials
- Stack Overflow
- YouTube
- W3schools
- Balsamiq for wireframes
- Adobe for resizing images
- PNG to ICO for converting png to ico for favicon
- removebg for removing background images
- Transparent Textures for creating background image
- Canva for creating logos and some images
- Multi Device Website Mockup Generator for mockup
- Autoprefixer for parsing CSS and add vendor prefixes
- W3C Markup Validation Service for testing HTML code
- W3C CSS Validation Service for testing CSS code
- jshint for testing JavaScript code
- PEP8 Online for checking Python code compliance
- Chrome DevTools for testing, style checking and debugging
Testing report is available TESTING.md
β Typos β
There are a few issues caused by typos and mislocating bracket. Nothing technical and these are just careless mistakes but spend some time trying to figure out what wrong it is. The solution for this is to be more careful of what you type, especially, something that the editor does not pick up as an error and need to be patience to go through each code again.
β Text Wrap β
For some reason, some texts in heading are not wrapped and just keep going to the right. Look up the solution on the internet and found that word-wrap: break-word;
CSS code can be used to prevent this.
β Retrieving Data in List β
On edit_recipe
function, data needs to be retrieved from the database. Not sure how to do it for the data in a list so look up the solution on the internet and find a Stackoverflow post that gives me the solution for this.
β Targeting Specific Delete Item in Modal β
Set up a modal for delete function to prevent users from deleting items unintentionally, however, when modal is open, it targets the first item and not the specified item. Not sure what the issue is but keep testing it and come up with an idea of putting object id as a part of id (id="modal-delete{{ recipe._id }}"
) and somehow make it work.
β Form Validation β
There are some headings for dropdown menus for creating recipes. Even though those headings are disabled, users actually can submit it, if they do not open the options in the dropdown menu, and it stores an empty value in the database. It causes issues for category_name
as there must be a value for this. Try a few ways to solve the issue and come up with an idea to allocate "other" as a category. Currently form is validated by HTML only but by using Flask form validation WTForms, this might be achieved better, however, this is a new module for me and currently do not have time to learn it so decide to keep the form as it is.
β Pagination β
Initially, no plan to implement this on the project but as the number of recipes increases, decide to do it to make the website look better. Watch Corey Schafer's youtube tutorial, follow Pagination Demo but cannot make pagination work. Find a recent post on slack about pagination so follow the threads and then look at Ed Bradley's code on his project and use it to make it work. It works as pagination but still do not understand the logic of this very well
β Defensive Programme β
There is a certain restriction on accessing pages or recipes. For example, create recipe page can be accessed by logged-in users, edit recipe can be accessed by the recipe owner only, so a good defensive programme is required to prevent non-authorised users from accessing them. Defensive programme when users logged-in is achieved easily (e.g. User A tries to access user B's recipe) however when a user is not logged in and do a manual test, it gives me a KeyError: "user". Try a few different codes including try and except, talk to my mentor however the issue is still there so decide to post it on slack. There is feedback from someone suggesting if "user" in session:
can be used for this, and as per his suggestion, use if "user" in session:
and able to set us a defensive programme.
β Object ID β
When an incorrect object id is typed on URL with edit_recipe
and edit_category
(which should not happen under normal circumstances but discover this error during some manual testings), it shows a bson invalid error. Look up solutions on the internet and find three possible ways. First, try to set the number of objct id and equal to 24. Second, use bson.objectid.ObjectId.is_valid(recipe_id)
with if statement. Third, define o as object id and check to see if it matches with actual object id. None of them works so post the query on slack community hoping someone might give me advice on this. Get no response and as getting nowhere to solve the issue, contact tutoring support. A tutor suggests using try and except blcok
but also asks me how to solve the issue. Explain what I try to do and he suggests to check if bson is fully imported for my second solution. Import bson and use bson.objectid.ObjectId.is_valid(recipe_id)
with if statement but does not work so he suggests try and except block
that checks object id validation, then to process it or lead to error page. As per his suggestion, use try and except block
and no error is given when an incorrect object id is manually put and also led to the error page.
Git as a local repository and GitHub as a remote repository are used for the project, and below is how I use them as the version control for the project.
β Setting Up β
-
Create a remote repository in GitHub by clicking "New repository" on the main page
-
Use Code Institute Template, put the repository name and click Create Repository making sure to select public
-
Open the repository with Gitpod which is my Integrated Development Environment (IDE). By using Code Institue Template, initialisation including initial commit is done so no need to do
git init
command when open IDE, or to usegit push -u origin main
command for my first commit.gitignore
file, which is very important for the project including some confidential information, is created with Code Institute template so not necessary to create it
β Commitments β
- When a section or even a group of work is completed, it is committed in git and pushed into GitHub, to make sure to keep the history of the work logged properly and not to lose the work in unexpected situations. Below commands are used for this.
* git status | To check the status of new/modified folders, files, and documents
* git add . | To put all new and updated work on the stage in git
git add <specific file> is used when different types of work are done but do not want to commit everything on the same commitment
* git commit -m "Example commit" | To commit the work on the stage in git before pushing it to GitHub
* git push | To update the repository in GitHub for main branch
git push origin <branch name> is used when pushing git into GitHub for sub-branches
Note:
During the project, I learn a better way of keeping commit messages so follow this article
β Branches β
- When some testing is needed, create a branch and test is on it instead of using main branch. When the testing is successful, then merge the branch into main, when it is not, leave the branch unmerged and keep working on main branch. Below commands are used for this.
* git branch <branch name> | To create a new branch
* git checkout <branch name> | To switch branch
* git branch | To check current branch
* git merge <branch name> | To merge sub-branch into main, do this on main branch
Note:
Same sub-branch can be used as many times during the project, however, create a new branch for each testing because my knowledge of git is not the best and sometimes not 100% sure if things are done right. Hope to improve more on the version control using git for future projectsThere is one commit message does not correspond to what happen. Commit it from sub branch presuming there are only minor changes, however, it seems it does it from main branch somehow
The website of this project requires back-end technologies such as server, application, and database so the website is deployed in Heroku, which is a cloud platform with a service supporting several programming languages, because GitHub can only host a static website. There are two ways to deploy a website in Heroku. One is to use Heroku Command Line Interface (CLI) and another one is to connect to GitHub repository. Connecting to GitHub repository is much easier and recommended by a tutor so this website is deployed by using GitHub method.
Before deploying the website to Heroku, there are three important steps to follow to make the app work in Heroku correctly.
- Create
requirements.txt
file that contains the names of packages being used in Python. It is important to update the file if other packages or modules are installed during the project - Create
Procfile
that contains the name of the application file so that Heroku knows what to run. Procfile may have a blank line when it is created so remove it as it may cause problems - Push them into GitHub
Once those steps are done, the website can be deployed and below are the steps of the deployment in Heroku.
-
Create an account in Heroku
-
Click New & Create new app to create a new app
- Put an App name, which must be unique, Choose a region and click create app
- Go to Deploy section and click Connect to GithHub
- Search for the repository by the repository name and connect it
- Before clicking Enable Automatic Deploys, hidden variables such as IP address, PORT, SECRET_KEY, MONGO_URI and MONGO_DATABASE need to be recorded in Heroku. Go to Settings, click Reveal Config Vars and fill out necessary keys and values
- Once all the hidden variables are recorded, then click Enable Automatic Deploys and click Deploy Branch (Main should be selected unless you want other branches to be deployed)
- When the app is deployed by Heroku correctly, there is a confirmation message and you can access the app
Note
It is important NOT to setdebug=True
when you deploy the website. As this is a project for my study, I keepdebug=True
even after the deployment but only while the app is being built and make sure to change it todebug=False
before the submission
β HTML5 β
- MDB Navbar for navigation bar
- MDB Forms & Input for input forms
- MDB Cards for recipe summary display
- MDB Modal for delete confirmation & recipe instructions
- Bootstrap Dropdowns for dropdown menus
β CSS3 β
- Html Code Generator for speech bubble
- Codepen CSS Bouncing Arrow for bouncing arrow
β JavaScript β
- Sanwebe for adding input fields
β Python β
- Ed Bradley for pagination
Note: All credits are also mentioned on the files
β Recipes β
All recipes are from BBC Good Food
- Triple chocolate & peanut butter layer cake
- Rustic bread
- Hedgehog rolls
- Lemon biscuits
- Seed & grain cottage loaf
- Ginger biscuits
- Easy vanilla cake
- Florentine biscuits
- Easy millionaireβs shortbread
- Mary Berryβs orange layer cake
- Chocolate fudge crinkle biscuits
- Luscious lemon baked cheesecake
- Honey & almond layer cake
- Manchego & chorizo melting biscuits
- Soft burger buns
- Easy sourdough bread
- Basic granary bread dough (for rolls or a large loaf)
- Ham & tomato Stromboli
- Turkish-style sharing bread
- Dundee cake
- Vanilla cupcake bouquet
- Pistachio & milk chocolate squares
β Affiliate β
All affiliates are from Amazon Affiliate Programe
- Cake Decorating Equipment
- Set of 8 Non Stick Baking Tray
- Stainless Steel Angled Icing Spatulas
- Kenwood Mary Berry Special Edition Chef Elite Stand Mixer
- Mary Berry's Baking Bible
- Russell Hobbs 23620 Compact Fast Breadmaker
Note:
According to the handbook, actual affiliate is not recommended so image is used from Amazon affiliate but usetag=faketag
and link to only item page
β Logo & Favicon & Other Images β
I would like to thank ;
- My mentor, Spencer Barriball, for going through the project with me and giving me some advice especially to improve UI and UX
- Ed Bradley for giving me advice on several queries that I have during the project
- Code Institute Tutor, Alan, for giving me a guidance on how to solve an issue
- Code Institute Tutor, Igor, for giving me a guidance on how to solve an issue
- Code Institute Slack Members for giving me advice on queries that I have during the project