As one of the more difficult trends of the UK lockdown, Starter is an e-commerce website that aims to simplify the processes involved in baking with sourdough. The website offers recipes and useful tools of the trade (available for purchase). A number of free recipes are provided, with paid membership required for access to premium recipes.
Please use the following card number for test purposes: 4242 4242 4242 4242
-
Information Architecture
-
Technologies Used
-
Testing
-
Credits
- Easily understand the purpose of the website and the services it offers
- Be able to navigate intuitively through the site
- Browse all products and recipes
- Browse via product category
- Search for product and/or recipe by name or description
- Easily see what I've searched for and the search results
- As a Returning User, I want to easily select the quantity of a product to be added to the basket
- View items in my basket to be purchased
- Be able to adjust the quantity of individual items in my basket
- See an order confirmation after checkout
- Receive an email confirmation after checkout
- Easily find how to become a member
- Learn about becoming a premium member
- Easily login and logout
- Receive an email confirmation upon registering
- Recover my password in case I forget it
- Save/update my shipping information
- View my order history
- View premium content
- See when new premium content is added
- View which subscription service is enabled
- Easily cancel a subscription service
- View my next subscription payment date
- Add a product
- Edit/update a product
- Delete a product
- Add a recipe
- Edit/update a recipe
- Delete a recipe
- Ensure all subscriptions payments are up to date
- Customise the homepage to include featured products/recipes
The overall design is clean and simple, reflecting the the purpose of the website.
- Colour was used minimally in order to not detract from the content.
- Bootstrap colours were used on icons in toasts to signal different responses:
- Success = BS Success
- Info = BS Info
- Error = BS Danger
- Warning = BS Warning
- 'Special Elite' was used for headings and titles as well as the main logo. This type-writer like font was chosen to give the impression of a story or a book.
- 'Knewave' was used to promote premium content to make it look like a poster.
- 'IBM Plex Sans' was used for all other text. It was chosen for its readability.
- A range of font sizes and weights were used to denote importance.
- All fonts had Sans Serif as the back-up font.
Bootstrap's 'img-fluid' class was used on the majority of images to ensure responsivity.
All product imagery is sized at 640 x 640px based on this Magenest article.
All recipes images are sized at 1200 x 800px based on this Wordpress forum.
Illustrations were taken from the above Adobe stock image and used throughout the website, complimenting the title/logo font by creating the impression of a story or book.
The membership promo was created in the image of a poster to grab the user's attention and direct them to the premium membership page.
The 'No Image' image is used in the event that an image is not uploaded for a product or recipe.
Icons are used throughout the site to provide the user with visual cues and create a more interesting aesthetic.
- Chevron icons are used throughout, to indicate directional links.
- Social media icons are clearly positioned to the left of the footer and are constantly available to the user. Dead links are used as the social media pages to exist at present.
- A crown icon is used when to denote premium membership.
- Bootstrap's Grid System was used throughout to create the layout and make it responsive.
- Bootstrap was used in conjunction with custom spacing and colours to provide much of the styling for the site. This includes all buttons, cards and nav bars.
- Django Crispy Forms was used to automatically style form elements.
- Stripe Elements was used to style the product checkout.
- Stripe Checkout was used for the subscription/premium membership checkout.
-
Account options differ depending on user:
- Not logged in:
- Sign In
- Sign Up
- Logged in:
- Account
- Sign Out
- Admin/Superuser:
- Product Management
- Recipe Management
- Update Premium Memberships
- Account
- Sign In
- Sign Out
- Django/Python checks whether a user is logged in or not with
if request.user.is_authenticated
and whether the user is a Superuser withif request.user.is_superuser
to display the correct navigation to the user.
- Not logged in:
-
- The main navigation and account collapse in to a burger nav icon.
- The subheading of the logo is dropped.
-
- Dropdowns were used to reserve space.
- The background is solid white to prevent any background interference.
-
Search
- The promo banner is placed at the top of the screen to immediately alert the user of promotions.
- The banner is removed on mobile views to reserve space.
- Bootstrap toasts are used to provide feedback to the user for certain actions, e.g. adding/removing a product, signing in/out.
- The toast also provides a running summary of the user's shopping basket and link to proceed.
- To reflect the nature of the website, the footer only contains the bare necessities; social links and contact email.
-
The homepage immediately directs the user to shop for either ingredients or tools. Clicking either will take the user to their specified shopping category.
-
Both the Product and Recipe modal contain a boolean field called 'featured'
-
The home app uses python to filter recipes/products by 'featured' which are passed in to a Django template and sliced to display the correct amount for the layout:
for recipe in featured_recipes|slice:":1"
for product in featured_products|slice:":8"
-
To the left, a promotional poster is displayed to encourage the user to become a member. Clicking navigates user to the premium purchase options.
- The Promo Poster was created to alert the user to the website's premium membership.
- A Slick Carousel is used to display featured products.
- An overlay is used to display information, this is on hover-over on larger screens and constant on smaller screens.
- Bootstrap cards were used to display product information
- Logic to display product count of selected filter:
{{ products|length }}
- User's are able to sort products by a number of options to make shopping easier.
-
The quantity buttons use Javascript to overlay the default plus/minus buttons to fit with the style of the website.
-
The Add to Basket uses python/Django to add the specified quantity of the specified product to the shopping basket. If successful, a success toast is triggered with a summary of the shopping basket and the items are stored in the session.
-
Edit/delete buttons are visible if the user is a Superuser:
if request.user.is_superuser
.
Python logic is used to prevent the user from adding products to their basket that are out of stock or exceed the amount of inventory currently in stock.
-
If a product has 0 Inventory, the 'Add to Basket' button is disable and a message is displayed.
-
If a product exceeds the amount of inventory currently in stock a toast is displayed and the product is not added to the basket.
- The information is laid out in clear way to allow user's to review for proceeding.
- The user is able to update the quantity of the item or remove the item before proceeding to checkout.
- Keeps a running total of all products and shipping.
- If the total amounts to less than the free shipping threshold a message is displayed to inform the user of how much more they have to spend to qualify for free shipping.
- The 'Continue to Secure Checkout' is the most prominent button on the page to direct the user to the checkout.
- The keep shopping button takes the user back to products.
- The user is displayed a summary of what they are about to purchase for final review.
-
The form combines stripe elements with crispy forms to provide the logic and styling.
-
Contact Information:
- If the user is anonymous, they are prompted to sign / in or register to save their contact information. This will be related to the user's profile.
- If the user is logged in (
if user.is_authenticated
) a checkbox to save shipping information is visible: - If ticked the shipping information is then saved on the user's profile. This time saving feature makes user's more likely to proceed with a purchase in the future.
- If a required field is left empty the user is alerted and prevented from proceeding:
-
Payment Information:
-
Completing payment
- Provides user's with a summary of their order and informs them that an email has been sent to their account as assurance.
- Python/Django checks if profile has membership attached with
if profile.membership
- If the user is not logged in or does not have a membership they are encouraged to become a premium in order to access premium content:
- If the user has a membership:
- The recipe cards feature a large photo, recipe title and a free or premium tag.
- Having both free and premium content shows the user the quality of the recipes making them more likely to want to access the premium content.
- Python/Django checks if the recipe is premium with
if recipe.premium
and displays the correct tag accordingly:
- Python/Django handels whether a user has premium membership to access premium recipes:
if request.user.userprofile.membership
- A Bootstrap accordion is used to show/hide subsections of the recipe.
- Ingredients are rendered using a bootstrap table for clarity.
- Edit/delete buttons are visible if the user is a Superuser:
if request.user.is_superuser
.
- Bootstrap images cards are used to display the two payment options.
- The cars are of one whole image split in two for visual impact and continuity.
- Overlaid text is white and has a text-shadow to ensure readability.
- Clicking on either takes the user to checkout with specified option.
- The promotional offer displayed in the banner is repeated below the payment options as a reminder to users before proceeding.
- The user must have profile, to which the membership will be attached, to access this page.
- If the user is not logged in / does not have a profile they will be redirected to the Sign-In page:
- If the user already has a membership they will be redirected to their account:
- The premium basket mirrors the shopping basket for continuity.
- The information is laid out in clear way to allow user's to review for proceeding.
- The user is informed that promo codes can be entered at the next stage.
- A back button is provided in case the user wants to change payment option.
- Stripe Checkout is used to render information and handle payment of subscriptions.
- If the user goes clicks the back arrow they are re-directed to the transaction cancelled page to reassure them that they will not be charged:
- Stripe creates the subscription
stripe.checkout.Session.create
.
- If the transaction is successful, the membership will be attached to their account and the user will be able to see the changes immediately.
- Successful payment is confirmed by the checkout success page.
- If the user has previously purchased something and ticked the Save Shipping Details checkbox at checkout this form will be populated with the saved information.
- Users can update this information to populate the contact information on the Product Checkout page.
-
Python/Django inserts the most recently added recipe.
-
The settings button takes the user to their membership settings.
- Displays user's order history in a Bootstrap table.
- Clicking the order number takes the user to the specified order summary, that mirrors that of the Product Checkout Success page, with an altered message:
- This page retrieves information from the user's specific Stripe Subscription
stripe.Subscription.retrieve(request.user.userprofile.stripe_subscription_id)
and renders it to the display. - The Cancel Membership triggers a defensive modal:
- If cancelled, the Stripe Subscription information is altered to stop taking payments and end of the next billing period and the following page is now displayed using
{% if cancel_at_period_end %}
:
- The Product management page can only be accessed by superusers, if a non superuser attempts to access the page
if not request.user.is_superuser
they are redirected back to the homepage with the following message:
- Allows superusers to add a product.
- All required fields are labelled with *.
- The select image field is customised with Javascript for better UI
- If a required field is left empty the user is alerted and prevented from proceeding.
- If the product is added successfully a success message is triggered.
-
Mirrors the Product management page but with fields populated with the specified product.
-
The image field shows a preview of the current image using custom Javascript:
- Has the same layout and features as the add product page.
- A forset is used to link the ingredients to the recipe.
- The user is able to control how many/few ingredients are on a recipe using the more button or delete checkbox.
- Failing to check delete on empty ingredients will result in a form error.
- The Recipe Management has the same layout and features as the edit product pages.
- This button syncs the Stripe Subscription information with the Django user profile membership settings.
- It returns a HTTP response to inform the user that the request was successful:
- It is recommended that this is done regularly to ensure consistency.
- Allauth pages are used throughout for authentication purposes.
- The allauth base template has been customised to match the rest of the website's styling for example:
- Product Variants
- Such as size and colour
- Filtering options on recipes
- Such as breakfast, lunch, dinner, vegan, vegetarian etc.
- Stock control Dashboard
- For admin to better see and understand their stock levels
- Stripe elements on subscription checkout
- Currently, the UI for the subscription checkout is purely from Stripe Checkout. In the future I would like to implement Stripe Elements so that Subscription Checkout matches the Product Checkout
- Delete ingredients buttons in Recipe Management
- Custom JavaScript / Rest API for delete ingredients buttons to improve UX/UI
- Link products to recipes and vice versa
- So that users are able to shop the products needed for specific recipes
- Social account login / Signup
- I am currently awaiting verification in order to implement allauth social account login
SQLite is used in development and PostgreSQL is used in deployed version.
-
- Amazon S3 bucket is used to store product/recipe images uploaded to the website
-
- Used to create images of each page displayed on different screen sizes for this readme file
-
- Used to help make the website responsive on a range of devices as well as various interactive elements
-
- Used to create and edit images
-
- Used with django-crispy-forms to format all forms
-
Django: + various extensions
- Python Web framework used to develop the website
-
- Font Awesome icons were used throughout
-
- The Gitpod terminal from Git was used to commit to Git and Push to GitHub
-
- Used to store the code after being pushed from Git
- Used to import font styles into the style.css
- Used for deployment
- User in conjunction with Bootstrap for interactive components
-
- User to for install tools needed in this project
-
[Reduce Images]https://www.reduceimages.com/
- Used to compress images
-
- Slick carousel was used to create the carousel on the homepage
-
- Used to handle all payments
See testing.md
Required tools:
- Gitpod or other IDE
Must be installed on your machine:
- PIP
- Python 3 or above
- If using an IDE other than Gitpod: Git
-
Navigate to this project's github repository https://github.com/irahbt/starter
-
Above the list of files, click "Clone"
-
The default is to clone the repository using HTTPS, under "Clone with HTTPS", to clone the repository using an SSH key click "Use SSH"
-
Click the icon next to the link to copy your link
-
Open terminal
-
Change the current working directory to the location where you want the cloned directory
-
Clone repository with terminal command:
git clone <paste copied link>
- Install all required modules with terminal command:
pip -r requirements.txt
- Create a
requirements.txt
file with terminal command:
pip freeze > requirements.txt
- Create a
Procfile
with terminal command
echo web: python app.py > Procfile
-
git add
andgit commit -m
the new requirements in terminal and Procfile and thengit push
the project to GitHub. -
Create an account on Heroku
-
Once logged in, create a new app by clicking the "New" button in your dashboard. Give it a name and set the region to Europe.
-
Confirm that the heroku app is linked to the correct GitHub repository.
-
On the Heroku dashboard for the app, go to "Settings" > "Reveal Config Vars".
-
Set the following config vars:
- See Django, AWS and Stripe documentation for secret keys.
- See Emails below for email variables.
-
In the heroku dashboard, go to "Deploy"
-
In the heroku dashboard, click "Deploy"
-
Select deployment method > "GitHub"
-
Select "Enable Automatic Deployment"
-
Make sure master branch is selected
-
Click "Deploy Branch"
-
Once app has been built, click "View" to launch your deployed app
Setting up emails with Gmail
- Create account
- Go to Settings > Accounts and Import > Change account settings > Other Google Account settings
- Got to Security tab > Signing in to google > Turn on 2 step verification > Set device to mail and chose a name
- Add the password and host e-mail to your Heroku Config Vars
- Product descriptions were adapted from various similar product descriptions.
- Recipes were adapated from the following:
- Soft and Chewy Sourdough Chocolate Chip Cookies
- No Knead Soft Sourdough Rolls
- Sourdough Flatbread Recipe
- Other recipes were given by friends and family
-
Images were sourced from:
-
Reduce Images was used to compress images
-
Real Favicon Generator was used to generate the website's favicon.
-
Icons from Font Awesome
-
Bootstrap code was used throughout.
-
Code was adapted from the Code Institute's Boutique Ado project
-
The following resources were used to guide the creation of:
-
Stripe Subscription
-
Recipe Ingredients Formset
-
Inventory:
-
Special thanks to my Code Institute mentor, Dick Vlaanderen, for his guidance throughout this project.
Also, a big thank you to my Mum for providing inspiration in the form of freshly baked sourdough loaves.