- Project Overview
- UX & User Stories
- Design & Wireframes
- Database Schema
- Features
- E-commerce & Payments
- SEO
- Marketing
- Security Features
- Technologies Used
- Testing
- Deployment
- Credits
A full-stack Django e-commerce application for purchasing jewelry products.
Velora Jewelry operates under a Business-to-Consumer (B2C) e-commerce model. The platform allows customers to browse and purchase jewelry products directly through a secure online checkout system.
Revenue Model:
- Single-payment transactions via Stripe
- Direct online product sales
- No subscription model currently implemented
Value Proposition:
- Affordable, stylish, and modern jewelry
- Secure and streamlined checkout process
- Easy account management and order tracking
Growth Strategy:
Future expansion may include:
- Limited-edition collections
- Email marketing campaigns
- Social media promotions
- Potential subscription-based VIP offers
- Sell handcrafted jewelry products online (B2C model)
- Provide a seamless and secure checkout experience
- Build brand visibility through SEO and social media marketing
- Collect customer emails for future promotions and product launches
As a user, I want to register an account so that I can purchase jewelry products.
-
The registration form includes: first name, last name, email, phone number, password, and password confirmation.
-
Email input must be validated for correct format validation.
-
Password must be at least 8 characters long.
-
Password confirmation must match the original password.
-
Clear validation error messages are displayed for invalid input.
-
After successful registration, the user is automatically authenticated and logged in.
-
The navigation bar reflects the user's authentication status.
As a user, I want to log in and log out so that my account remains secure.
-
The login form includes email and password fields.
-
Only registered users with valid credentials can log in.
-
Invalid credentials display a clear error message.
-
A logout option is visible only to authenticated users.
-
After logout, the user is redirected to the home page.
-
The navigation bar correctly reflects the user's authentication status on all pages.
-
Restricted pages require authentication and redirect unauthenticated users to the login page.
As a logged-in user, I want to see my login status so that I know I am authenticated.
-
The logged-in user's username or email is displayed on all pages.
-
The navigation menu updates dynamically based on login state (e.g., “Login/Register” → “Logout/Profile”).
-
Unauthorized users cannot access user-specific content.
-
Login status updates immediately after login or logout without requiring a page refresh.
-
Any changes in authentication state (login/logout) are reflected consistently across all templates.
As a logged-in user, I want to view my profile so that I can see my purchase history.
- The profile page displays all relevant user information: first name, last name, email, and phone number.
- A list of past purchases is displayed with order details including product name, quantity, price, and purchase date.
- Users can update their contact information; validation ensures correct format for email and phone number.
- Only authenticated users can access the profile page; unauthorized users are redirected to the login page.
- Navigation links dynamically reflect login state and allow easy access to the profile page.
- Any updates made to the profile are saved to the database and reflected immediately in the user interface.
As a user, I want to browse available jewelry products so that I can choose items to buy.
-
The main shop page lists all available products clearly.
-
Each product displays a name, price, image, and short description.
-
Products can optionally be filtered or sorted by category, type, or price.
-
Clicking on a product navigates to a detailed product page showing full description, images, and stock availability.
-
The layout is responsive and user-friendly across devices (desktop, tablet, mobile).
-
Navigation allows users to easily return to the main shop page from product detail pages.
As a user, I want to view detailed information about a product so that I can make an informed purchasing decision.
- The product detail page displays the product name, full description, price, and images.
- Optional attributes such as stock availability, SKU, size, or material are shown if available.
- An “Add to Cart” button is present, even if the checkout system is not yet implemented.
- Navigation allows users to return to the main product list easily.
- Product images are displayed in a user-friendly gallery or slider if multiple images exist.
- Page layout is responsive and maintains readability on desktop, tablet, and mobile devices.
As an admin, I want to add new products so that I can sell jewelry items.
-
Access to the “Add Product” page is restricted to admin users only.
-
The product creation form includes the following fields: product name, full description, price, image upload, category/type, stock quantity, and optional SKU.
-
Validation ensures all required fields are completed and that price is a positive number.
-
Clear success messages are displayed after a product is successfully added.
-
Clear error messages are displayed for invalid input or missing required fields.
-
After adding a product, the admin is redirected to the product list or detail page for confirmation.
-
Uploaded product images are properly stored and displayed in the admin and shop views.
As an admin, I want to edit product details so that I can keep product information up to date.
-
Only admin users have access to the “Edit Product” page.
-
Admin can update product information including name, full description, price, category/type, stock quantity, SKU, and images.
-
Validation is applied to all updated fields (e.g., price must be a positive number, required fields cannot be blank).
-
Successful updates display a clear success message; errors display descriptive messages.
-
After editing, changes are immediately reflected in the product detail page and shop listings.
-
If images are updated, the new images are stored and displayed correctly, replacing the previous ones if necessary.
As an admin, I want to delete products so that I can remove unavailable items.
- Only admin users can access the “Delete Product” functionality.
- Attempting to delete a product triggers a confirmation prompt to prevent accidental deletions.
- Once confirmed, the product is removed from the database and immediately disappears from shop listings and product detail pages.
- Deleting a product also removes associated images from storage, if applicable.
- Success or error messages are displayed to confirm the outcome of the deletion.
- The system prevents deletion if the product is part of a pending order and notifies the admin appropriately.
As a logged-in user, I want to securely pay for a product so that I can complete my purchase.
-
The checkout page displays a secure payment form integrated with Stripe.
-
Payment amount is automatically calculated from the products in the cart and cannot be altered by the user.
-
Payment data is transmitted securely over HTTPS and encrypted in compliance with Stripe standards.
-
Users cannot bypass the payment process to gain access to products or order confirmation.
-
Upon successful payment, the user receives a clear confirmation message and order summary.
-
Failed payment attempts display a descriptive error message and allow retrying.
-
The system creates an order record in the database only after a successful payment transaction.
-
Payment status is reflected in the user’s profile / purchase history immediately after completion.
As a user, I want to receive confirmation when my payment is successful so that I know my order has been placed.
-
After a successful payment, a clear success message is displayed on the checkout page.
-
An email confirmation is sent to the user with order details (optional but recommended).
-
The order status in the database is updated to “Paid” or equivalent.
-
Users are redirected to a detailed order summary page showing purchased items, quantities, total price, and order date.
-
The order summary page is linked from the user’s profile / purchase history for easy reference.
-
Payment confirmation is secure and cannot be faked by manipulating URLs or browser behavior.
As a user, I want to receive a clear error message if my payment fails so that I can try again.
- A descriptive error message is displayed to the user when a payment fails.
- No order record is created in the database for failed payments.
- Users can retry the payment for the same cart without losing their items.
- All failed payment attempts are logged in the system for admin review.
- Error messages clearly indicate the reason for failure when possible (e.g., card declined, network error, invalid details).
- Users are guided to corrective actions (e.g., retry, use another card, or contact support).
- The system prevents duplicate charges if the retry is attempted.
As a user, I want to be prevented from accessing restricted pages so that my data remains secure.
-
Non-authenticated users are redirected to the login page when trying to access protected pages.
-
Users cannot access or view other users’ data, including profiles, orders, or cart contents.
-
Access permissions are enforced on the server side, not just via frontend navigation.
-
Attempts to access restricted pages are logged for security review.
-
Protected pages show an appropriate message or redirect notice when access is denied.
-
Admin-only pages are completely restricted to admin users; unauthorized access attempts redirect or block users.
As an admin, I want to have access to administrative functionality so that I can manage the store.
- Access to all admin functionality (add/edit/delete products, manage orders, view reports) is restricted to authenticated admin users.
- Non-admin users attempting to access admin pages are redirected or shown an access denied message.
- Admin login is required; session handling ensures secure authentication.
- All admin actions (add/edit/delete product, update orders) are logged for auditing purposes.
- Navigation and UI elements for admin functionality are visible only to admin users.
- The system enforces server-side checks to prevent unauthorized access even if frontend links are manipulated.
As a user, I want clear navigation so that I can easily find products and pages.
-
Main navigation is visible on all pages.
-
Navigation includes links to Home, Shop, Cart, and Profile/Login.
-
The active page is visually indicated to help users know their location.
-
Navigation is fully functional and responsive on both desktop and mobile devices.
-
Users can easily return to the home page from any page.
-
Dropdowns, if any, are accessible and usable via keyboard for accessibility.
As a user, I want to receive meaningful feedback messages so that I understand the result of my actions.
-
Success messages are displayed after key actions such as login, purchase, or form submission.
-
Error messages are displayed for invalid actions, form errors, or failed processes.
-
All messages are clear, user-friendly, and convey the exact outcome.
-
Messages can be dismissed by the user or automatically disappear after a reasonable time.
-
Messages are consistent in style and placement across the site for easy recognition.
-
Feedback is provided for both frontend validation and server-side errors to prevent confusion.
As a user, I want to be redirected to a helpful page if I attempt to access a non-existent URL.
- A custom 404 error page is displayed when a user accesses an invalid URL.
- The 404 page includes clear navigation options to Home and Shop.
- The user is not shown a default server error page.
- The 404 page maintains the site's consistent design and branding.
- A friendly message explains that the page cannot be found.
- The error is handled gracefully without crashing the application.
As a site owner, I want the site to be search-engine optimised so that more users can find it online.
-
Each page includes a unique and descriptive page title relevant to its content.
-
All pages contain meaningful meta descriptions to improve search visibility.
-
A valid sitemap.xml file is generated and submitted for indexing.
-
A properly configured robots.txt file is implemented.
-
No placeholder text (e.g., Lorem Ipsum) is present in the final project.
-
Images include descriptive alt attributes for accessibility and SEO.
-
Semantic HTML elements (e.g.,
, ,, ) are used appropriately. -
URL structures are clean, readable, and SEO-friendly.
As a user, I want to sign up for a newsletter so that I can receive updates and promotions.
-
A newsletter signup form is available on relevant pages (e.g., footer or homepage).
-
Email input includes proper validation (correct format, no empty submission).
-
Duplicate email entries are prevented.
-
A clear confirmation message is displayed after successful signup.
-
The email address is stored securely in the database.
-
Newsletter data handling complies with data protection principles (e.g., consent).
As a site owner, I want to promote my products through a Facebook Business Page so that I can increase brand awareness.
- A Facebook Business Page is created for the brand.
- The page includes the brand name, logo, and clear business description.
- Sample product posts or promotional content are published.
- A screenshot or mockup of the page is included in the README documentation.
- A link to the Facebook page is included in the website footer.
Wireframes were created prior to development to plan the layout and structure of each page. They were designed using Claude AI and reflect the intended user interface for both desktop and mobile views.
| Page | Wireframe |
|---|---|
| Home | ![]() |
| Shop | ![]() |
| Product Detail | ![]() |
| Cart | ![]() |
| Checkout | ![]() |
| Profile | ![]() |
| Login and Register | ![]() |
The application uses a relational database to support authentication, product management, and secure order processing.
The database will include the following core models:
- User (Django authentication model)
- UserProfile
- Category
- Product
- Order
- OrderItem
- Newsletter (optional feature)
All relationships will be enforced using foreign key constraints and follow relational database best practices.
A detailed schema description and Entity Relationship Diagram (ERD);
erDiagram
User ||--o{ Order : places
User ||--|| UserProfile : has
Product }o--|| Category : belongs_to
Order }o--|| Product : contains
User {
int id PK
string username
string email
string password
}
UserProfile {
int id PK
int user_id FK
string default_phone_number
string default_street_address1
string default_street_address2
string default_town_or_city
string default_county
string default_postcode
string default_country
datetime created_on
datetime updated_on
}
Category {
int id PK
string name
string slug
}
Product {
int id PK
int category_id FK
string name
string slug
string product_type
text description
string short_description
decimal price
int stock
bool featured
image image
datetime created_at
}
Order {
int id PK
int user_id FK
int product_id FK
int quantity
decimal price
datetime date
}
Note: The cart is session-based and does not require a database model. Cart data is stored in Django's session framework.
- Product Browsing – Users can browse the full jewelry catalogue, view products details, images, descriptions, and pricing information.
- Shopping cart – Users can add products to their cart, adjust quantities, remove items, and view an automatically updated order summary before checkout.
- Stripe checkout – Secure payment processingis provided through Stripe integration, allowing users to complete purchases safely.
- Authentication – User can register, log in, and log out securely. Authentication-protected features are restricted to authorized users.
- Product Search and Filtering – Users can search for products and filter results to quickly find items that match their preferences.
- Order Confirmation – Users receive confirmation after a successful purchase, ensuring clear feedback on completed transactions.
- Featured Products Carousel – Selected products are highlighted on the homepage through a dynamic carousel to showcase featured items and promotions.
- Responsive Design – The application is designed to provide a consistent user experience across desktop, tablet, and mobile devices.
Administrators can manage products using the Django admin panel, including creating, updating, viewing, and deleting products.
Staff users can also access a frontend “Add Product” interface to create new products directly from the website. Frontend add product is restricted to staff users only.
Access to admin functionality is restricted using Django authentication:
@staff_member_requiredis used to protect admin-only views.is_staffis used to separate admin users from regular authenticated users.user.is_authenticatedensures only logged-in users can access protected features.
SEO was a core focus of this project. The following techniques were implemented to improve discoverability and search engine ranking.
A dynamic XML sitemap is generated using Django's built-in django.contrib.sitemaps framework. It includes all product detail pages, category listing pages, and static pages (Home, About, Contact).
The sitemap is accessible at /sitemap.xml.
📄 View implementation: shop/sitemaps.py · velora_jewelry/urls.py
Live Sitemap:
https://velora-jewelry.onrender.com/sitemap.xml
A robots.txt file is served from the root URL to guide web crawlers. It allows indexing of public pages and disallows crawling of sensitive areas.
📄 View file: robots.txt
Sitemap: https://velora-jewelry.onrender.com/sitemap.xml
Every page includes a unique <title> and <meta name="description"> tag, defined in the base template and overridden per page using Django template blocks.
📄 View implementation: templates/base.html · shop/templates/shop/product_detail.html
Open Graph tags are implemented to improve how pages appear when shared on social media platforms such as Facebook, Instagram, LinkedIn, and X (Twitter). These tags provide custom page titles, descriptions, images, and URLs, creating rich link previews that enhance visibility and user engagement.
📄 View implementation: templates/base.html · shop/templates/shop/product_detail.html
This implementation ensures that shared links display a meaningful title, description, representative image, and canonical URL, providing a more professional and engaging appearance across social platforms.
- Semantic HTML5 elements (
<header>,<main>,<section>,<nav>,<footer>) used throughout - Descriptive
altattributes on all product images - Human-readable slugs for all product and category URLs (e.g.
products/rose-gold-dainty-tennis-bracelet/) - No placeholder or Lorem Ipsum text in the final project.
Velora Jewelry is designed for consumers who appreciate minimalist and elegant jewelry at an affordable price point.
Primary Target Audience :
- Women aged 18–45
- Men aged 18-50
- Individuals interested in minimalist, and modern jewelry
- Active on social media platforms such as Instagram and Facebook
- Online shoppers comfortable with digital payments
Secondary Target Audience :
- Gift shoppers purchasing jewelry for partners, friends, or family members
- Budget-conscious consumers seeking stylish yet affordable pieces
- Young professionals looking for everyday elegant accessories
Customer Needs :
The target audience values:
- Secure and seamless online shopping
- Clear product descriptions and high-quality images
- Trustworthy payment processing
- Easy account management and order tracking
Facebook Business Page Mockup :
A Facebook Business Page mockup was created for Velora Jewelry to support organic social media marketing. The page includes the brand name, logo, business description, and sample promotional posts to demonstrate the brand's social media presence.
A link to the Facebook Business Page would be included in the website footer in a production environment.
Newsletter signup :
A newsletter signup form is available in the site footer. Subscriber email addresses are collected and stored securely in the database for future marketing campaigns, product launches, and promotional offers.
This provides a direct communication channel with customers and supports customer retention and repeat purchases.
Organic search traffic is supported through the SEO techniques implemented throughout the project, including:
- Dynamic
sitemap.xml - Configured
robots.txt - Unique page titles and meta descriptions
- Open Graph tags for social sharing
- Semantic HTML structure
- Descriptive image alt attributes
- SEO-friendly URLs
| Feature | Action | Expected Result | Pass/Fail |
|---|---|---|---|
| User Registration | Create new account | User is registered and redirected to homepage | Pass |
| User Login | Login with valid credentials | User is logged in successfully | Pass |
| Product Browsing | View homepage/products page | All products are displayed with images, price, and description | Pass |
| Product Search | Click the search icon in the navbar | Redirected to Shop page where products can be searched by keyword | Pass |
| Product Filtering | Apply filters | Products are filtered based on selected criteria | Pass |
| Add to Cart | Click “Add to Cart” button | Product is added to shopping cart | Pass |
| Update Cart | Change product quantity | Cart updates total price automatically | Pass |
| Remove from Cart | Remove item from cart | Item is removed successfully | Pass |
| Stripe Checkout | Complete payment process | Payment is processed successfully and an order record is created | Pass |
| Order Confirmation | Complete checkout | Confirmation page is displayed with order details | Pass |
| Admin Add Product (Django Admin) | Add product via admin panel | Product is created and appears in store | Pass |
| Frontend Add Product (Staff only) | Add product via site interface | Success message is displayed and the product is added to the product list | Pass |
| Authentication Protection | Attempt to access checkout without authentication | User is required to log in and is redirected to the login page | Pass |
| Staff Restriction | Attempt to access Django admin as a non-staff user | User cannot access the admin panel and is shown a message requiring a staff account | Pass |
All manual tests were performed both locally and on the deployed Render application. The results confirmed that core functionality, authentication, authorization, product management, cart operations, and payment processing work as expected in both environments.
All pages were validated using the W3C Nu HTML Checker. Rendered page source (View Page Source) was used for validation to avoid false errors from Django template tags.
| HTML Validation | W3C Validator |
HTML validation flagged heading hierarchy warnings (e.g. h1 jumping to h4/h5). These are structural improvements noted for future refactoring and do not affect functionality or user experience.
Python code was checked using Flake8 to ensure compliance with PEP8 standards. Due to time constraints, several style issues remain, such as line length and whitespace inconsistencies. These do not affect the functionality of the application.
Lighthouse was used to evaluate performance, accessibility, best practices.
- Performance: 65
- Accessibility: 88
- Best Practices: 77
- The navigation menu correctly displays Login and Register links for unauthenticated users.
- After successful login, the user’s username is displayed in the navbar dropdown along with Profile and Logout options.
- After logout, the navbar updates immediately and displays Login and Register again.
- After logout, the navbar updates immediately and displays Login and Register again.
- The same login page is shown when an unauthenticated user manually attempts to access /profile, confirming that protected routes are restricted.
| Bug | Cause | Fix |
|---|---|---|
| Product creation returned 500 error | Incorrect model/form handling | Fixed form validation and correctted model save logic |
| User profile update failed | Missing POST request handling | Added proper POST handling and form save validation |
| Broken navigation links | Incorrect URL routing in templates | Updated URL mappings in URL Django templates |
| Bestseller filter showing all products | sort=bestseller passed in URL but view expected bestseller=1 as a separate param; checkbox was incorrectly disabled by removeEmptyParams() |
Moved bestseller out of sort options into a standalone checkbox filter; updated home link to ?bestseller=1; added removeEmptyParams() to main.js with checkbox type guard; added auto-submit on checkbox change |
| User profile page failed to load (500 error) | Orders were being sorted by date, but the Order model uses created_at as the timestamp field |
Updated the profile view to order user orders by created_at, restoring profile functionality |
- The Contact Us form requires further refinement to improve message submission feedback.
- The wishlist feature may require additional optimization and testing following its implementation during the final development stage.
- Improve responsiveness across smaller mobile devices and tablet screens.
- Add dynamic wishlist updates without page refresh.
- Enhance contact form functionality with confirmation messages and improved validation.
The application is deployed on Render using a production-ready configuration with a PostgreSQL database.
During development, the application uses SQLite for simplicity. In production, it uses a Render PostgreSQL database to provide reliable and scalable data storage. Media files are hosted on Cloudinary, and sensitive configuration values are managed using environment variables.
The following Environment Variables are set in Render (Dashboard → Environment Variables):
| Key | Value |
|---|---|
SECRET_KEY |
Django secret key |
DATABASE_URL |
Render PostgreSQL database URL |
STRIPE_PUBLIC_KEY |
Stripe publishable key |
STRIPE_SECRET_KEY |
Stripe secret key |
STRIPE_WH_SECRET |
Stripe webhook secret |
CLOUDINARY_URL |
Cloudinary API URL |
EMAIL_HOST_USER |
Email address |
EMAIL_HOST_PASS |
Email app password |
-
Push the project to GitHub.
-
Create a new
Web Serviceon Render and connect the GitHub repository. -
Create a
PostgreSQLdatabase on Render.- Add the required environment variables in the Render dashboard:
- SECRET_KEY
- DATABASE_URL
- CLOUDINARY_URL
- STRIPE_PUBLIC_KEY
- STRIPE_SECRET_KEY
- STRIPE_WH_SECRET
- Email configuration variables (if applicable)
- Add the required environment variables in the Render dashboard:
-
Set the build command:
- $ pip install -r requirements.txt
-
Set the start command:
- $ gunicorn core.wsgi:application
-
Update ALLOWED_HOSTS to include your Render domain.
-
Run database migrations:
python manage.py migrate- Create a superuser (if required):
python manage.py createsuperuser- If deploying to a new database, load the product fixture:
python manage.py loaddata products.jsonSummary This deployment ensures the application runs in a secure, scalable, and production-ready environment with proper separation between development and production settings.

















