(Developer: Vilayat Kleer)
- Project Goals
- User Experience
- User Stories
- Design
- Technical Design
- Technologies Used
- Features
- Validation
- Testing
- Bugs
- Deployment
- Credits
- Acknowledgements
- Be able to create meal plans to become a better meal-prepper
- Be able to edit or delete my meal plans at any given time
- Have an overview of all my meal plans for a set week
- Get inspired by finding new recipes
- Create an application that helps users track and prep their meals
- Provide users with a database full of recipes for them to choose and get inspired by
- Provide feedback to users on any important action (CRUD, log in, log out etc.)
- Deliver an aesthetically pleasing design to the application that makes users want to come back
- People who want to keep track of their daily meals
- Meal preppers who want an organised space for their meal plans
- Cooking enthusiasts who want to get inspired by new recipes without looking on multiple websites
- A simple, elegant application that anyone can use
- Clear feedback provided after performing an important action
- Providing a personal touch by referring to the users' username and first name throughout the application
- As an anonymous user, I want to be able to view the home page, so I know what the application is about
- As an anonymous user, I want to be able to view the recipe list, so I get a taste of what the application has to offer
- As an anonymous user, I want to be able to create an account, so I can start using the application
- As a registered user, I want to be able to log in with my account
- As a registered user, I want to be able to create a meal plan for a specific date
- As a registered user, I want to be able to add meals to a meal plan
- As a registered user, I want to be able to edit any of my meal plans
- As a registered user, I want to be able to delete any of my meal plans
- As a registered user, I want to have a weekly overview of my meal plans in my meal planner
- As a registered user, I want to be able to pick the first day of the week of my weekly overview
- As an registered user, I want to be able to view the recipe list
- As a registered user, I want to be able to view the details of each recipe in the recipe list
- As a registered user, I want to be able to view my account details on my profile page
- As a registered user, I want to be able to delete my account on my profile page
- As a registered user, I want to be able to log out when I'm done
- As a registered user, I want to receive feedback after performing an important action
- As the application owner, I want users to be able to filter recipes by meal type, diet type or by using the search bar
- As the application owner, I want to restrict most of the applications' functionality for anonymous users to encourage them to create an account
- As the application owner, I want users to stay on the application when they receive an HTTP response of 400, 403, 404 or 500
- As the application owner, I want users to be able to contact me with a contact form
- As the application owner, I want users to be able to find me on GitHub
- As the application owner, I want the users' input on forms to be validated
- As the application owner, I want users to be able to navigate around the application easily
- As the application owner, I want to provide a responsive application for all devices
The colours I used for the application have been picked using the Adobe Color Wheel. I first found a 'main' colour that I wanted to use (#407464, used in the bg-main class) before moving on to the other colours. The 'Split Complementary' colour harmony rule suggested a dark pink colour, which I took and customized to a soft grey-pink colour (#f5e4e4, used in the bg-accent class) to make it easier to look at and use in the application. Finally, I simply took the main colour and made it a few shades darker to use for the navbar and footer (#2e4b42, used in the bg-main-dark class).
The fonts that I used are Reem Kufi Fun for the logo, Montserrat for all the headings and Quicksand for all other text elements. They are all sans-serif fonts, but have a few distinct differences: The Montserrat font creates a nice contrast with the other text elements by having a simple design and bold font-weight, while the Quicksand font is more playful, yet legible. The Reem Kufi Fun font stands out from the other fonts with its unique 'W', which is why I found it to be suitable for the logo. All fonts have sans-serif as a fallback.
The application uses common web design conventions and is structured in an intuitive, easy to use way. Each page has a header and subtitle to clearly state its purpose and colour is used sparsly to increase both readability and keep the design clean.
The navigation bar has a logo on the left and the links to the right. When the screen size is too small to display the links, the menu turns into a collapsable menu with the familiar 'hamburger' icon.
The footer is at the bottom of the page and contains links to my Github page and a contact form.
The application contains the following pages:
- The index page with an introduction to the application and a brief overview of its features
- The sign up page where new users can create an account
- The log in page where users can log in to the application
- The log out page where logged in users can log out of the application
- The meal planner page where:
- Logged in users will see a weekly overview of their meal plans
- The date of the first day can be picked to generate a new weekly schedule
- New meal plans can be created by clicking on the '+' button to take users to the 'Add meal plan' page
- Existing meal plans can be edited by clicking on the pen button to take users to the 'Edit meal plan' page
- Existing meal plans can be deleted by clicking on the bin button, triggering a modal for confirmation, after which the meal plan will be deleted
- The create meal plan page where logged in users can create a new meal plan for the selected date, allowing up to 10 meals per meal plan
- The edit meal plan page where logged in users can edit an existing meal plan by changing or deleting meals from the plan
- The recipe list page where users can browse all recipes
- Users can filter by meal type (breakfast, lunch, dinner, snack), diet type (vegetarian, vegan) or simply use the search bar
- The recipe page where logged in users can find the recipe ingredients and instructions and a picture of the finished meal
- The profile page where logged in users can find their username, first name, email address, creation date and a 'Delete account' button if they wish to have their profile delete
- The 'Delete account' button triggers a modal for confirmation, after which the users' account and all its associated data will be deleted
- The contact page where users can contact me to leave feedback, report bugs, or simply send a message
- Logged in users will have the 'Name' and 'E-mail address' fields pre-populated with their data and cannot be edited
- The 400, 403, 404 and 500 pages to handle HTTP responses and keep users inside the application flow
The backend of the application is built with Python and the Django framework, with a PostgreSQL database attached via Heroku. The models in the meal and mealplanner app are used to create the entire database along with the models from Allauth.
The User model comes from the Allauth library and contains information about the user.
The Calendar model is used to create the weekly overview on the meal_planner page. It contains the following fields:
- user
- contains User as a foreign key
- picked_date
- day_one
- day_two
- day_three
- day_four
- day_five
- day_six
- day_seven
The MealPlanner model is used to save each users' meal plans. It contains the following fields:
- user
- contains User as a foreign key
- meal_plans
- contains MealPlan as a many to many field
The MealPlan model is used to save and contain all the meals that have been added to it. It contains the following fields:
- meal_planner
- contains MealPlanner as a foreign key
- date
- meal
- contains Meal as a many to many field through MealToMealPlan
Is used as an intermediate model between the MealPlan and Meal models. It contains the following fields:
- meal
- contains Meal as a foreign key
- meal_plan
- contains MealPlan as a foreign key
Arguably the most important model as the whole application revolves around it. It is used to populate the meal plans, recipe list and recipe pages. It contains the following fields:
- name
- image
- description
- ingredients contains Ingredient as a many to many field through IngredientToRecipe
- type
- contains MealType as a foreign key
- diet
- contains Diet as a foreign key
- prep_time
- contains PrepTime as a foreign key
- cook_time
- contains CookTime as a foreign key
Is used as an intermediary model between the Meal and Ingredient models. The reason it is called 'IngredientToRecipe' and not 'IngredientToMeal' is because the ingredients are only used on the recipe page. Contains the following fields:
- ingredient
- contains Ingredient as a foreign key
- meal
- contains Meal as a foreign key
- amount
Is used to hold the ingredients that are used on the recipe pages. Contains the following field:
- ingredient
Is used to set the meal type of each meal. Contains the following field:
- type
Is used to set the diet type of each meal. Contains the following field:
- diet
Is used to set the prep time for each meal. Contains the following field:
- prep_time
Is used to set the cook time for each meal. Contains the following field:
- cook_time
- Git was used for version control
- GitHub was used as a remote repository to store the all project files
- Gitpod was used as the IDE to write the project code
- Heroku was used to deploy the project
- PostgreSQL was used to store the project data, specifically the 'Heroku Postgres' add-on
- Google Fonts was used to supply the fonts for my project
- Font Awesome was used to supply the icons for my project
- WC3's Markup Validation Service was used to validate my HTML code
- W3C's CSS Validation Service was used to validate my CSS code
- JShint was used to validate my JavaScript code
- PEP8 was used to validate my Python code
- Coverage was used to produce reports on my python unit tests
- Google Chrome's DevTools was used to benchmark the applications' performance, accessibility, best practices and SEO
- Wave WebAIM's web accessibility evaluation tool was used to validate my Python code
- Bootstrap 5.1 was used for the application layout and some of the styling
- Cloudinary was used to store static files
- Crispy Forms was used to nicely format the forms used in my project
- Crispy Bootstrap 5 was used to install the Bootstrap 5 template pack for Crispy Forms
- Summernote was used for the meal description field on the admin page, allowing me to style the preparation instructions
- Allauth was used to take care of the accounts in the project
The website has a total of 15 features:
- Font Awesome icon combined with a Google Fonts font is used as the logo, placed on the left as is conventional
- Is present on every page
- Is responsive and works on all screen sizes
- Covers user story 23 and 24
- At the bottom of the page as is conventional, using the same colour as the navigation bar for consistency
- Contains a link to my GitHub account, using a Font Awesome GitHub icon
- Contains a link to the contact page, using a matching Font Awesome icon
- Is present on every page
- Covers user story 21 and 24
- Flash messages are displayed to users when performing any important action, like creating, editing or deleting a meal plan or logging into their account, providing them with meaningful feedback
- No screenshots provided here - all flash messages can be seen in action under Manual Testing - User Stories
- Covers user story 16
- Introduces users to the application
- Provides a brief overview of the applications' features
- Contains call-to-action buttons to the meal planner (if users logged in, otherwise a 'Create account' button is shown), recipe list and contact form
- Covers user story 1, 18
- Allows new users to create an account
- Users need to provide their email address, username, first name and a password
- The email address and username have to be unique
- All input is validated
- After their account has been created, Users are automatically logged in and taken to the meal planner page
- Flash message is displayed after account has been created
- Covers user story 3, 22 and 16
- Allows returning users to log in to their account
- Users need to enter their username and password - an empty or semi-empty form cannot be submitted
- All input is validated
- Users are taken to the meal planner page after successfully logging in
- Flash message is displayed after users have logged in
- Covers user story 4, 22 and 16
- Allows logged in users to log out of their account
- Flash message is displayed after users have logged out
- Covers user story 15 and 16
- Allows users to view their account details, listing their username, first name, email address and creation date
- Allows users to delete their account should they wish to do so
- Instead of a separate page, a modal is used to confirm if the user wishes to delete their account
- Flash message is displayed after users have deleted their account
- Covers user story 13, 14 and 16
- Provides users with a weekly overview of their meal plans
- Allows users to pick the first day of their weekly overview, allowing them to look back at past meal plans or plan ahead
- Provides a link to the 'Add meal plan' page
- Provides a link to the 'Edit meal plan' page
- Allows users to delete an existing meal plan
- Instead of a separate page, a modal is used to confirm if the user wishes to delete a specific meal plan
- Flash message is displayed after the user has deleted a specific meal plan
- Covers user story 8, 9, 10 and 16
- Allows users to create a new meal plan for the selected date
- Allows users to add up to 10 meals
- Flash message is displayed after a meal plan has been created
- Covers user story 6 and 16
- Allows users to edit their selected, existing meal plan
- Allows users to delete and add any available meal, limited to a maximum of 10 meals
- Flash message is displayed after a meal plan had been updated
- Covers user story 7 and 16
- Allows both anonymous and registered users to browse all available recipes
- Provides a link to the recipes' page, which only registered, logged in users can access
- Covers user story 2, 11, 16 18
- Contains the recipes' name preparation time, cooking time, meal type, diet type and image in the header
- Contains the recipes' ingredient list
- Contains the recipes' preparation instructions
- Provides a button to take users back to the recipe list
- Covers user story 12
- Allows both anonymous and registered users to filter all available recipes
- Users can filter by meal type (breakfast, lunch, dinner and snack)
- Users can filter by diet type (vegetarian, vegan)
- Users can filter by using the search bar
- Users can combine the meal type, diet type and search bar filters
- Covers user story 17
- Allows both anonymous and registered, logged in users to send me a message via a contact form
- The contact form contains a name, email address and message field, all of which are required
- If a registered user is logged in, their name and email address are automatically added to the corresponding fields - the fields cannot be edited
- Flash message is displayed after the form has been successfully submitted
- Covers user story 20, 22 and 16
- Keeps users in the application flow if they encounter an error by displaying a custom HTTP response page
- Contains a button that takes users back to the home page
- Covers user story 19
The HTML of the application has been validated using W3C's Markup Validation Service. all of the pages pass with no errors or warnings.
The CSS of the application has been validated using W3C's CSS Validation Service. It passed with no errors or warnings.
The JavaScript of the application has been validated using JSHint. It passed with no errors or warnings.
The Python code has been validated using Pep8 Validation Service - no errors or warnings were found.
Screenshots of mealplanner Python files PEP8 Validation
The accessibility of the application has been measured using the Wave WebAIM web accessibility evaluation tool - all pages pass without errors.
The performance of the application has been measured with Google Lighthouse with either a perfect or near perfect score on each page.
- As an anonymous user, I want to be able to view the home page, so I know what the application is about
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Home page | Go to the deployed application | Be informed about the applications' purpose and features | Works as expected |
- As an anonymous user, I want to be able to view the recipe list, so I get a taste of what the application has to offer
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Recipe list page | Click on the 'Recipe list' link in the navbar | Be able to view the recipe list despite not having an account or being logged in | Works as expected |
- As an anonymous user, I want to be able to create an account, so I can start using the application
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Create account page | Click on the 'Register' link in the navbar, the 'Create account' button on the homepage or the 'Create account' button on the recipe list page | Be able to create an account | Works as expected |
- As a registered user, I want to be able to log in with my account
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Login page | Click on the 'Log in' link in the navbar | Be able to log in to my account | Works as expected |
- As a registered user, I want to be able to create a meal plan for a specific date
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page, add meal plan page | Click on the 'Meal planner' link in the navbar, then click any of the '+' buttons to create a meal plan for that date | Be able to create a meal plan | Works as expected |
- As a registered user, I want to be able to add meals to a meal plan
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page, add meal plan page | Click on the 'Meal planner' link in the navbar, then click any of the '+' buttons to create a meal plan for that date, add meals to the meal plan | Be able to add meals to a meal plan | Works as expected |
- As a registered user, I want to be able to edit any of my meal plans
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page, edit meal plan page | Click on the 'Meal planner' link in the navbar, then click on the pen button of the meal plan you want to edit | Be able to edit a meal plan | Works as expected |
- As a registered user, I want to be able to delete any of my meal plans
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page | Click on the 'Meal planner' link in the navbar, then click any on the trash button of the meal plan you want to delete | Be able to delete a meal plan | Works as expected |
- As a registered user, I want to have a weekly overview of my meal plans in my meal planner
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page | Click on the 'Meal planner' link in the navbar, then look at the weekly overview | Be able to see a weekly overview of meal plans | Works as expected |
- As a registered user, I want to be able to pick the first day of the week of my weekly overview
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page | Click on the 'Meal planner' link in the navbar, then click on the calendar icon under 'Pick a date for day 1:', select a day, then click on the 'Pick day' button | Be able to see a new weekly overview, starting from the day I picked | Works as expected |
- As an registered user, I want to be able to view the recipe list
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Recipe list page | Click on the 'Recipe list' link in the navbar | Be able to view the recipe list | Works as expected |
- As a registered user, I want to be able to view the details of each recipe in the recipe list
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Recipe list page, recipe page | Click on the 'Recipe list' link in the navbar, then click on any of the recipes in the list | Be able to view the details of a recipe I clicked on | Works as expected |
- As a registered user, I want to be able to view my account details on my profile page
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Profile page | Click on your username in the navbar to open a dropdown menu, click on the 'Profile' link | Be able to view my account details | Works as expected |
- As a registered user, I want to be able to delete my account on my profile page
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Profile page | Click on your username in the navbar to open a dropdown menu, click on the 'Profile' link, then click on the 'Delete account button, confirm in the modal that you want to delete your account by clicking on the 'Yes, delete my account' button | Be able to delete my account | Works as expected |
- As a registered user, I want to be able to log out when I'm done
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Logout page | Click on your username in the navbar to open a dropdown menu, click on the 'Log out' link | Be able to log out of my account | Works as expected |
- As a registered user, I want to receive feedback after performing an important action
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Home page, login page, log out page, contact page, meal planner page, create meal page, edit meal page | Perform an important action, like logging in or out, creating a new meal plan etc. | Have a flash message displayed | Works as expected, as can be seen on each individual feature - the feedback message is highlighted in the screenshots |
- As the application owner, I want users to be able to filter recipes by meal type, diet type or by using the search bar
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Recipe list page | Click on the checkboxes underneath 'Meal type', select an option underneath 'Diet type, use the search bar to find a recipe, or combine them | Be able to gilter recipes | Works as expected |
- As the application owner, I want to restrict most of the applications' functionality for anonymous users to encourage them to create an account
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Meal planner page, recipe page | Look at the navbar or try to open a recipe when not logged in | Have no meal planner option and be unable to open a recipe - will redirect to the login page | Works as expected |
- As the application owner, I want users to stay on the application when they receive an HTTP response of 400, 403, 404 or 500
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Custom HTTP response page 404 | Enter a non-existing page name at the end of the apps' url | Have a custom 404 error page be displayed | Works as expected |
- As the application owner, I want users to be able to contact me with a contact form
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Home page, footer, contact page | Scroll down on the home page and click on the 'Contact us' button or scroll down on any page and click the envelope icon in the footer | Be able to submit a contact form | Works as expected |
- As the application owner, I want users to be able to find me on GitHub
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Footer | Scroll down on any page and click the GitHub icon in the footer | Open a new tab to my GitHub page | Works as expected |
- As the application owner, I want the users' input on forms to be validated
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Login page, logout page, create account page, contact page | Try to submit form without filling out the required fields or enter invalid data, like a partial email address | Have a warning message display and be unable to submit the form | Works as expected |
- As the application owner, I want users to be able to navigate around the application easily
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
Any page | Click on the corresponding link in the navbar, or the corresponding buttons on a parent page | Be taken to the correct page | Works as expected, as can be seen in all of the feature screenshots |
- As the application owner, I want to provide a responsive application for all devices
Feature | Action | Expected Result | Actual Result |
---|---|---|---|
The whole application | Resize any page | Have the page be formatted correctly for any device | Works as expected |
Some automated testing was carried out with by using Pythons' built-in unittest library. The screenshots that I added below are from the reports that were created by using coverage.
Bug | Fix |
---|---|
Contact form too big when logged in, styling not consistent | Change column size of name field from md-6 to md-12 to take up the whole column, add input tag to styling rule - link to commit |
Icons in footer too small | Change styling rule to specifically target anchor elements inside the list that holds them - link to commit |
Bootstrap modal stopped working after upgrading to Bootstrap 5 | Change data attributes to data-bs attributes - link to commit |
Footer not at the bottom of the page if content doesn't push it down | Set body height to 100vh, display to flex and flex direction to column. Then set the footers' margin-top to auto - link to commit |
Footer not at the bottom of the page if content doesn't push it down | Set body height to 100vh, display to flex and flex direction to column. Then set the footers' margin-top to auto - link to commit |
Scripts not working properly | Accidentally had scripts outside of body tag, moved them inside - link to commit |
CreateMealPlan view doesn't grab the correct meal planner when creating a meal plan | Used the wrong user attribute, change from user.username to user.id - link to commit |
Diet filter not working anymore | Accidentally deleted span that is used to target the right recipes, add it back in - link to commit |
Meal plans can no longer be created | Crispy forms required a different set up to work properly with my form and formset, added proper formartting to make it work again - link to commit |
This website was deployed using Github Pages with the following steps:
- Go to your Github Repository
- Navigate to the 'Settings' page
- On the left hand menu under 'Code and automationo', click on 'Pages'
- Under 'Source', click on the 'Branch' dropdown element and set it to your main branch (in my case, this branch is called 'main')
- Click on 'Save'
- Refresh the page and you will be provided with a link to your deployed Github Page.
If you want to fork this repository, follow these steps:
- Go to the Github repository (https://github.com/vkleer/CI_PP4_WhatsCooking)
- Click on the 'Fork' button in the top right corner under the navigation bar
If you want to clone this repository, follow these steps:
- Go to the Github repository (https://github.com/vkleer/CI_PP4_WhatsCooking)
- Click on the 'Code' button above the list of files
- Select your preferred way of cloning, I recommend using the 'GitHub CLI' option
- Under 'GitHub CLI', click on the copy button to copy the clone command
- In you IDE, open Git Bash
- Navigate to the working directory where you want to clone this directory
- Paste in the clone command you copied and press the 'enter' key to create the clone
This application has been deployed using Heroku with the following steps:
- Login to Heroku
- Go to your Heroku dashboard
- In the top-right corner, click on the 'New' button, followed by the 'Create a new app' button
- Enter an app name (it has to be unique) and choose your region under the 'Choose a region' dropdown menu.
- Click on the 'Create app' button
- On the next page, click on the 'Settings' tab
- Under 'Config Vars', click on 'Reveal Config Vars' to add a new Config var - this is where you can store sensitive data, like your Google service account key
- Under 'Buildpacks' click on the 'Add buildpack' button to install additional dependencies. For this project the 'python' and 'nodejs' buildpacks were added, in that specific order
- Click on the 'Deploy' tab
- Under 'Deployment method', click on 'Github'. You can then search for your repository under 'Search for a repository to connect to'
- Click on the 'Connect' button to connect your repository
- On the next page, under 'Choose a branch to deploy' you can choose the branch you want to deploy your app from
- Either click on the 'Enable Automatic Deploys' button under 'Automatic deploys' to have the app deploy automatically on each push you make to the branch, or click on the 'Deploy Branch' button under 'Manual deploy'
- Wait for the app to build and be deployed. Once the app is ready, a message will be displayed saying 'App was successfully deployed' along with a button which takes you to your newly deployed app
To send emails from your website using Google's SMTP server, the following steps are required:
- Preferable, create a new Gmail account
- Following the instructions in this link, enable the less secure apps feature
- Under your settings.py, add the following settings:
- EMAIL_BACKEND = ‘django.core.mail.backends.smtp.EmailBackend’
- EMAIL_HOST = ‘smtp.gmail.com’
- EMAIL_USE_TLS = True
- EMAIL_PORT = 587
- EMAIL_HOST_USER = ‘[email protected]’ (I set this up in my env.py file and grab the variables using os.environ.get)
- EMAIL_HOST_PASSWORD = ‘your account’s password’(Again, this is set up in my env.py file and the variables are grabbed using os.environ.get)
- On Heroku, under settings, add two new Config Vars: EMAIL_HOST_USER and EMAIL_HOST_PASSWORD, using the same email address and password
- All images and the recipes themselves were found on BBC Food
- I wasn't quite sure how to structure my ingredients model, but this post from Stackoverflow helped me figure it out
- My ManyToMany fields weren't showing up on my admin panel, this post from Stackoverflow was very helpful
- I wanted to add extra fields to my sign up form, which I was able to do thanks to this post from Stackoverflow
- I was struggling to get next and previous days for my calendar, but this article helped me figure it out
- I wanted to set the intial field values of some forms to something specific, but didn't know how - [this post from Stackoverflow] was very helpful
- Though I had looked at project examples, I didn't quite understand how inline formsets worked - this video on YouTube was really a life saver
- I wanted to disable some of my form fields by default, that was possible thanks to this post on Stackoverflow
- I wanted anonymous users to be able to browse the recipe list, but not be able to open the actual recipe page. Luckily I found out that you can add a login decorator, thanks to this post from Stackoverflow
- To set up the contact form, I looked at some other users' projects and browsed the web for a good solution - in the end I decided to use Google SMTP, which was help set up thanks to this article on Medium
I would like to thank:
- My mentor Mo Shami for providing me with advice and guidance for this project
- My partner Lauren Baker for helping me with testing and finding multiple bugs in the program