Developer: Felix Lehmann
Render App: https://kern-suits.onrender.com/
Facebook Page: KERN | Frankfurt
Github: Kern Suits
This project simulates an exclusive suit boutique called Kern Suits, which offers high-quality suits and accessories to discerning customers. The platform allows users to purchase products online as well as book personal appointments for tailored fittings and style consultations.
The website follows a clean and sophisticated design aesthetic intended to communicate elegance while remaining approachable for a modern audience. Because today’s customers expect seamless mobile experiences, the entire project has been built following a mobile-first principle from the start. Moreover, an upcoming recommendation system and a personal profile area will further strengthen customer relationships and brand loyalty.
The challenges in this project mainly arose while working with Django’s MVT architecture. Although Django offers powerful abstractions for rapid development, there were several instances where implementing advanced customization required extensive research and experimentation. In particular, integrating Stripe payments with a custom order workflow and extending the user model to store measurement profiles proved to be technically demanding. By contrast, designing the data models for the appointment booking system and product catalog was relatively straightforward.
UPDATE NEW: 20/12/2025:
- bug fixes: see Bug Fixes, including:
- checkout process fix (server error 500 due to status value mismatch: 'paid' didn't exist, only 'created'.. )
- require login and require staff member to access the product management page
- implement SEO:
- keywords
- links
- metadata
- sitemap.xml + robots.txt
- Created a Facebook page
- documentation:
- add business model description
- add SEO chapter (metadata, keywords, sitemap.xml, robots.txt, links, FB page)
UPDATE (old): 10/10/2025:
- there is role-based login
- admin section was added (called "business center") where
- superusers and staff members can manage products (remove, add, change qty)
- superusers can remove/add user access rights
- email-based registration was added
- 404 page was added
- feel free to look at: https://github.com/users/flexirexi/projects/5
Currently existing user account with multiple bookings
- an admin account will be given personally to CI
- other accounts and profiles can be set up by simply signing up to this page.
Feel free to try it out
- Site Owner Goals
- Business Model
- SEO & Online Marketing
- User Stories
- Design & UX
- Features
- Data Models
- Technologies Used
- Accessibility
- Testing & Quality Assurance
- Deployment
- References & Credits
The main goal of this project is to build a distinctive, premium online presence for Kern Suits that combines modern technology with timeless style. The platform aims to establish a strong brand presence, enable scalable online sales, and integrate personal consultation options to achieve a high conversion rate. Additionally, it is designed to lay the groundwork for effective SEO, including targeted keywords, content marketing, and social media strategies to attract qualified traffic and maintain long-term customer relationships.
A hybrid menswear boutique combining an online retail store (ready-to-wear suits and accessories) with appointment-based services (fittings, alterations, and made-to-measure orders). Customers complete real purchases online, and can book a personal consultation to adjust fit, style, and future recommendations.
-
Who is the customer?
- B2C / individual customers
- Customers who value a premium, curated selection and a smooth checkout experience
- international EU-customers via shipping (export-ready for ready-to-wear). EU only because the shipping is free and outside the EU is of less value
-
What will they buy?
-
Products (ready-to-wear):
- Men's wear: shirts, jackets, trousers, waistcoats, ties, accessories etc.
- Product catalog with categories, stock numbers, variants (size, color, fit), and pricing
- Shipping cost handling (EU: free)
- Orders database to store: status, customer data, shipping address
- Ratings & reviews database
- Media storage for high-quality product images
- See: Data Models
-
Key website features:
- Search and filter options (size, fit, category, occasion)
- Stock visibility, sold out products won't be shown (pre-filtered)
- Order notifications (on-site )
- Clear product discovery (navigation + categories)
- User profile + authentication to speed up checkout and store delivery data
- Images must be high quality, as they are a core conversion driver
- please note: for the purpose of this project, I generated them with AI
- I created a huge dataset of product series and products. Then, I added for each series a description and for each product.
- These descriptions I prompted into the AI which then generated the pictures. It took a while but it was the most reasonable way to get images cheap.
- Product series descriptions + detailed product pages
- Checkout flow (Stripe)
- Possibility to book appointments for adjustments/consultations.
-
Product model:
- Product series -> products (suits, shirts, trousers, waistcoats, ties, accessories) -> variants (size, color, fit)
-
-
How will customers pay?
- Stripe credit card payments (single purchase)
- Please note: for the purpose of this project, please use
- the card number: 4242 4242 4242 4242
- the expiration date: 09/30
- CVC: 000
- Postal code/ZIP: 99999
-
Target audience:
- Kern Suits primarily addresses three main customer segments:
-
BUSINESS CUSTOMER: Ambitious Professionals Young and mid-career professionals who invest in quality suits for their daily business life, job interviews, and formal events. They value timeless elegance and appreciate the convenience of online ordering combined with expert personal advice.
-
EVENT CUSTOMER: Style-Conscious Occasion Shoppers Customers purchasing suits for special occasions such as weddings, gala events, or milestone celebrations. This group is often looking for guidance on fit, styling, and accessories to create a complete and confident look.
-
FASHION CUSTOMER: Style-Conscious Men Who Value Quality Customers who prioritize high-quality materials, expert tailoring, and a consistent brand experience. They appreciate having their preferences and measurements saved for future purchases, and often engage with the brand through newsletters, exclusive offers, and personal consultations.
-
- Kern Suits primarily addresses three main customer segments:
-
Revenue streams:
- Ready-to-wear product sales (online store)
- Made-to-measure orders via appointments (premium upsell)
- Alterations/fitting services (appointment-based)
-
Value propositions:
- Premium, curated menswear with a boutique feel online
- Hybrid model: online convenience + personal consultation (trust + conversion)
- Fit confidence through fittings, alterations, and optional measurement profiles
- International-ready: EU-export-friendly, ready-to-wear
- Secure checkout (Stripe) and a smooth, mobile-first shopping experience
- Good SEO increases the chance that the right customers find Kern Suits via search engines and purchase men's wear online.
- Combine (1) clear page intent + helpful content, (2) strong on-page structure (semantic HTML, metadata, internal linking), and (3) technical basics (sitemap/robots, performance) to rank for relevant queries.
- Google crawls websites and builds an index (so it can retrieve pages fast). When users search, Google ranks indexed pages based on usability (relevance to the query, geographical context, content quality, links/authority, and latest updates). The following methodologies seek to optimize search engine results.
- However, keywords in 2025 play only a very small role for SEO. Since, in this project, keywords are mandatory, we will discuss the research process below. Keywords for this project will be used as intents and embedded in informative texts, guides, headers and other content (to increase the website usability).
- Short-tail keywords (broad, competitive):
- Useful for brand visibility, but often attract a wide range of users who may not match Kern’s target audience
- Best used as “category intent” support (e.g., suit categories, occasions, locations), while the main focus should be on more specific keywords
- see Step 2 - Expand into keyword ideas
- Long-tail keywords (specific, lower competition):
- Better match for user intents (ready-to-wear vs alterations vs made-to-measure vs wedding vs expat/business)
- Often drive higher conversion because the search intent is clearer
- see Step 2 - Expand into keyword ideas
Keyword research process
-
Step 1: Define topic clusters (what Kern actually offers):
-
Ready-to-wear (in-stock) suits & accessories (online purchase)
-
Appointments: fittings, alterations, style consultation
-
Geography / Local SEO: Frankfurt + Rhein-Main (Wiesbaden, Mainz, Darmstadt, Bad Homburg, Hanau, Offenbach, Langen, Dreieich)
-
Made-to-measure suits via appointment (premium conversion path)
-
Frankfurt business context: expats + banking/business customers
-
Weddings (groom + occasion styling)
-
Export: international customers buying ready-to-wear online (shipping to the EU only)
-
Identity and language (Germany/Europe + "Denglish"):
- Kern Suits can intentionally use a German/European identity as a trust signal for EU users
- In the Frankfurt region, many searches are mixed German/English ("Denglish"). Keyword strategy should reflect this reality (not only pure English, not only pure German)
- such as herrenanzug maß frankfurt tailor shop, wedding suit frankfurt termin etc.,
- see Step 2 - Expand into keyword ideas
-
-
Step 2: Expand into keyword ideas (lists):
-
from cluster into related phrases (synonyms, occasions, customer types, locations)
-
Build patterns like:
{service} + {intent} + {location} + {language signal}List 1: Made-to-measure (MTM):
- made-to-measure suit Frankfurt
- made to measure suits Frankfurt
- custom suit Frankfurt
- tailored suit Frankfurt
- men’s made-to-measure Frankfurt
- suit fitting Frankfurt
- made-to-measure appointment Frankfurt
- maßanzug frankfurt made to measure
- maßanzug frankfurt tailor
- maßkonfektion frankfurt tailored
- anzug nach maß frankfurt appointment
- maßanzug termin frankfurt english
- suit fitting frankfurt maßanzug
- herrenanzug maß frankfurt tailor shop
List 2: Germany/Europe Identity:
- made-to-measure suit Germany
- European tailoring Frankfurt
- tailored suits in Frankfurt
- German tailoring Frankfurt
- Kern Anzüge Frankfurt
- Kern Suits Frankfurt
- Kern tailoring Frankfurt
- Kern made to measure Frankfurt
- Kern Maßanzug Frankfurt
- Kern Anzug kaufen Frankfurt
- Kern appointment Frankfurt
List 3: Expats/International Consultation:
- tailor for expats Frankfurt
- English-speaking tailor Frankfurt
- suit consultation in English Frankfurt
- international clients tailor Frankfurt
- business suit for expats Frankfurt
- corporate wardrobe Frankfurt
- tailor frankfurt english
- maßanzug frankfurt english consultation
- anzugberatung frankfurt english
- suit fitting frankfurt english appointment
- expat tailor frankfurt maßanzug
- tailor near me frankfurt english
List 4: Banking/Business (typical Frankfurt):
- business suits Frankfurt
- executive suits Frankfurt
- banker suit Frankfurt
- office suits Frankfurt
- interview suit Frankfurt
- classic navy suit Frankfurt
- business anzug frankfurt tailor
- banker suit frankfurt maßanzug
- anzug für bank frankfurt made to measure
- interview anzug frankfurt fitting
- office anzug frankfurt custom
List 5: Wedding:
- wedding suit Frankfurt
- groom suit Frankfurt
- made-to-measure wedding suit Frankfurt
- wedding suit consultation Frankfurt
- groomsmen suits Frankfurt
- wedding suits Rhein-Main
- hochzeitsanzug frankfurt tailor
- bräutigam anzug frankfurt made to measure
- wedding suit frankfurt termin
- anzug hochzeit frankfurt fitting
- groomsmen suits frankfurt maß
List 6: Ready-to-Wear/ Online shop (Germany):
- buy suit online Germany
- men’s suits online Germany
- suits shipped from Germany
- European suits online
- premium suits Germany shipping
- EU shipping suits Germany
- EU shipping suits
List 7: In-stock Intent:
- suits in stock Frankfurt
- ready-to-wear suits Frankfurt
- buy men’s suit Frankfurt
- suit shop Frankfurt
- anzug kaufen frankfurt in stock
- anzug shop frankfurt ready to wear
- herrenanzug frankfurt store
- suit store frankfurt anzug
- anzug online bestellen germany
- anzug versand international
- suits online germany shipping
- european suits online shop germany
List 8: Alterations/Adjustments (appointments):
- suit alterations Frankfurt
- tailoring alterations Frankfurt
- suit adjustments Frankfurt
- suit shortening Frankfurt
- suit fitting service Frankfurt
- anzug ändern frankfurt alterations
- anzug kürzen frankfurt tailor
- hose kürzen frankfurt suit alterations
- sakko ärmel kürzen frankfurt
- anzug enger machen frankfurt tailoring
- suit fitting frankfurt anpassung
-
-
Step 3: Validate with Google + keyword tools (capture real queries):
-
Google: Autocomplete suggestions
-
Google: 'Related Searches'
-
-
Step 4: Select final targets (keep intent + competition realistic):
-
Remove overly generic keywords that are dominated by major online shops and broad fashion sites.
-
Examples to cross out:
suits,menswear,fashion,tuxedo,tailor(too broad without context).List of exclusions (examples):
- made-to-measure suit
- tailored suits
- buy suits online
- tuxedo
- ties
- wedding suit
- men's wear
- bespoke tailor
- navy blue
- ...
-
-
Prefer keywords that match Kern’s offer and location context:
- Appointment intent, made-to-measure intent, alterations intent, wedding intent, expat/business intent, Rhein-Main local intent, export intent
- It turns out that, as soon as german words are used, Frankfurt pops up as a location. Obviously, it is because Frankfurt (metropolitan area) is a financial hub
- english buzzwords only shouldn't be used as either english speaking countries are searched the most or American cities
- suffixes like
for expats,english speakingare not often used but if, thenFrankfurtis a useful combination
-
-
Implementing keywords on the website:
-
Assign one clear intent per page (primary keyword theme per landing page)
- landing page: 'tailor german suits', 'tailored suits frankfurt'
- web shop: 'ready-to-wear suits frankfurt':
- appointment page: 'made-to-measure suit frankfurt', 'custom suits frankfurt'
-
Use semantic HTML and structured headings (one clear H1, supporting H2/H3)
-
Place key phrases naturally in: title, headings, intro copy, image alt text (where relevant), internal link anchors
-
The page content must match the search intent
-
Support SEO with: sitemap.xml, robots.txt, clean URLs, and strong internal linking
-
-
Internal links (site structure + discovery):
- Navigation should guide users to core conversion pages (in-stock shop, appointments, made-to-measure, weddings)
- Use descriptive link text (helps users and search engines understand the target page)
- Add meaningful aria labels where needed (accessibility + clarity)
-
External links (selective, quality-focused):
- Social links (open in new tab):
target="_blank"andrel="noopener"
- Social links (open in new tab):
-
Core meta elements (high impact):
-
Important note on
meta name="keywords":- Major search engines largely ignore the meta keywords tag for ranking
- It should be kept minimal
-
Technical helpers:
sitemap.xml+robots.txtfor crawl guidance- Open Graph tags for better sharing previews (social)
- Optional structured data (Schema) for business info and richer results (where applicable)
- Goal: Build trust and improve SEO by providing clear, helpful, high-quality content on the pages users land on first.
Landing page (home/first touchpoint)
-
What users need
- Instant understanding of what Kern Suits offers (ready-to-wear shop + appointments/made-to-measure)
- Trust signals (Frankfurt/Rhein-Main presence, German identity, secure payments, shipping)
- A clear next step (shop now/book appointments)
-
What information and features should be provided
- Short value statement and primary offerings (RTW, alterations, made-to-measure, weddings/other occasions)
- Key USPs (EU shipping, curated selection, fitting support, Stripe checkout)
- Strong calls-to-action (Shop/Appointments/ Made-to-measure/Wedding)
-
How to make the information easy to understand
- Use a simple structure: headline -> short intro -> 3–5 bullets -> CTA buttons
- Avoid jargon. Use short sentences and clear section headings
- Use visual hierarchy (H1/H2, spacing, icons, short blocks)
-
How to demonstrate expertise, authoritativeness, and trustworthiness
- Mention experience/craftsmanship and fit guidance (without overclaiming). Decency is key. This is the reason why there isn't a buy now/book now button everywhere. There are links at the top navigation bar and in the sections of the landing page with clear, accessible CTA-buttons.
- Show real-world proof: reviews, photos, process overview, clear policies (shipping/returns)
- Add transparent business info (location, contact, imprint, terms of conditions)
Web shop (products.html/product listing page)
-
What users need
- Quickly find the right product (size, fit, category, occasion)
- Confidence (quality, shipping, returns, authenticity, pricing clarity)
- Smooth path to purchase (cart -> checkout)
-
What information and features should be provided
- Strong filtering and search (size, fit, category, occasion)
- Clear stock visibility + variant selection hints -> please note that sold out variants are not listed here in the first place. There is no need to notify the user about 0 stock.
- Short category intro text (keyword-friendly) + trust details (EU shipping, secure checkout)
-
How to make the information easy to understand
- Consistent product cards (image, name, price, key attribute, availability)
- Clear sorting (price, newest, popular)
- Minimal clutter: avoid long paragraphs on listing pages
-
How to demonstrate expertise, authoritativeness, and trustworthiness
- Reliable shipping/returns information accessible from the shop -> in the terms & condition in the footer (internal link).
- Ratings and high-quality imagery
-
How to help users discover other parts of the app
- Add “Need help with fit?” link to Appointments / Fit guide
- Add cross-links to related categories and curated collections -> is handled by the products details page. As the series/collection is presented there, a dedicated page for that would be a duplicate.
-
What users need
- Decision-making information: fit, sizing, material, usage scenario, shipping/returns
- Confidence: clear images, authenticity, secure checkout, reviews
- Next actions: add to cart / choose variant / get fit help
-
What information and features should be provided
- High-quality images (multiple angles, close-ups)
- Clear sizing + fit guidance (and what to do if unsure)
- Material / care information, shipping costs, delivery time, returns
- Reviews/ratings and related product recommendations
-
How to make the information easy to understand
- Use sections with headings: Overview / Fit & sizing / Materials / Shipping / Returns
- Keep the main summary short; move details into collapsible sections if needed
- Use bullets for specs and key benefits
-
How to demonstrate expertise, authoritativeness, and trustworthiness
- Provide accurate, consistent product specs (no marketing fluff)
- Fit tips and "when to book an appointment" guidance (alterations / made-to-measure)
- Transparent policies (shipping/returns) and secure payment trust badges (Stripe)
-
Internal linking opportunities
- Link to: similar products, appointments (fit support), shipping/returns page
-
How to help users discover other parts of the app
- Related products, "complete the look" accessories, recently viewed. This is a special feature. Given that there are product series, products and product variants just make it mandatory to provide a horizontal scroll (carousel) to show other products of the same series.
- "Book a fitting" CTA for users unsure about size/fit
Social media promotion: Facebook page
-
1 Audience & platform fit (Who / where?)
- A FB has been set up - KERN | Frankfurt
- Kern Suits targets local customers in the Frankfurt/Rhein-Main area (business/expats and wedding shoppers)
- Facebook is suitable as a "low-effort, high-trust" presence where users can quickly verify the brand, location, and credibility
-
2 Content & user needs (What do users need and how to deliver it?)
- Users need trust signals and clarity: what Kern offers (ready-to-wear shop + appointments + made-to-measure), how to book, and what to expect
- Content that fits Facebook with minimal production overhead:
- appointment availability updates (fittings/alterations/made-to-measure)
- seasonal highlights (business suits, wedding season, new arrivals)
- short fit tips and "what to wear" guidance for business and weddings
- social proof (reviews, selected customer photos where allowed)
-
3 Goals, offers, and budget (How does it support business goals?)
- Main goal: increase trust and local discovery, then push users to high-intent pages (Shop /Appointments)
- Discounts should be rare to keep a premium positioning. Facebook can announce seasonal highlights but shouldn't become a "discounter"
- Budget approach: start organic (free/low-cost). Add small local ads only if needed (radius targeting around Frankfurt/Rhein-Main)
-
4 Facebook page layout and posts
-
1 Audience & reach (Who is it for and how do we capture them?)
- Creating (non-)marketing emails with MailChimp
- Best for users who already showed intent: account sign-ups, appointment bookings, customers, and interested visitors.
- Capture via low-friction sign-up points: footer, checkout, appointment page, and optional "fit guide" download.
-
2 Content & user needs (What emails provide real value?)
- Email is ideal for delivering useful, intent-based content that supports purchase and reduces uncertainty:
- new arrivals / best sellers (ready-to-wear)
- fit & sizing guidance (reduces returns, increases confidence)
- business wardrobe tips (Frankfurt expat/banking audience)
- wedding checklists and styling bundles (groom + accessories)
- appointment guidance (what to bring, timelines, how fitting works)
- Email is ideal for delivering useful, intent-based content that supports purchase and reduces uncertainty:
-
3 Goals, offers, and budget (What flows work best?)
- Goals: repeat purchases, higher conversion, fewer return issues, and stronger customer relationship (owned channel)
- Low-effort, high-impact flows (automation-friendly):
- welcome email (brand + key links)
- abandoned cart reminder (ready-to-wear)
- post-purchase follow-up (care tips + cross-sell accessories)
- appointment confirmation + reminders (reduce no-shows)
- Discounts: deliver via email first (most targeted). Keep promotions controlled to protect premium brand perception
- Budget approach: start with free/low-cost tooling and simple automation. scale later if ROI is proven
-
4 Non-marketing emails (transactional):
- Purchase confirmation email after successful checkout
- Order status update email whenever staff/admin changes an order status in the Business Center
- Newsletter subscription confirmation after enabling the newsletter
- Enable via: (1) dedicated newsletter signup page, (2) checkbox during registration, (3) checkbox in the profile page (enable/disable)
- Appointment confirmation emails for appointment creation, changes (reschedule), and cancellations
As a new Visitor:
- view a clean and stylish landing page
- see an about page, impressum
As an authenticated User:
- I want to register for a personal account, so that I can manage my orders and appointments.
- I want to log in to my personal account, so that I can access my profile and saved data.
- I want to reset my password if forgotten, so that I can regain access to my account.
- I want to edit my personal data (address, contact, size), so that I can receive accurate recommendations and smooth delivery.
- I want to see my order history, so that I can track what I have bought and when it will arrive.
- I want to book a personal appointment, so that I can get expert advice and fitting services.
- I want to manage my upcoming appointments, so that I can reschedule or cancel if needed.
- (optional) I want to delete my account, so that I can remove my data if I no longer wish to use the service.
As a buyer:
- I want to browse suits and accessories by size, style, occasion, and fit, so that I can easily find products that match my preferences.
- I want to view detailed product pages with high-quality images and fabric information, so that I can make informed purchase decisions.
- I want to filter and sort products, so that I can quickly narrow down the selection.
- I want to search products by name or category, so that I can locate specific items faster.
- I want to see customer ratings, so that I can gauge the quality and satisfaction levels.
- I want to add items to my shopping cart, so that I can buy multiple products in one transaction.
- I want to edit my cart, so that I can change quantities or remove products before checkout.
- I want to securely check out using Stripe, so that I can pay safely and conveniently.
- I can see an order confirmation after checkout, so that I can be assured that everything went well
- (optional) As a customer, I want to receive an email confirmation, so that I have proof of my purchase.
- I want to track my order and delivery status, so that I know when to expect my products.
- I want to review a product after purchase, so that I can share my experience.
- I want to edit or delete my reviews, so that I can update my feedback if necessary.
- (Optional) As a customer, I want to save favorite products to a wishlist, so that I can consider them later.
(not done yet:) As an admin:
- I want to view all products with CRUD controls, so that I can manage the catalog efficiently.
- I want to add new products, so that I can keep the assortment fresh.
- I want to edit product details, so that I can correct or update information.
- I want to delete products, so that I can remove outdated items.
- I want to manage customer orders and appointments, so that I can ensure smooth operations.
- (Optional) I want to moderate reviews, so that I can maintain content quality.
Wireframes provide a basic idea how to structure and design your templates. My wireframes look very simple but they also serve this very one purpose: the layout. Themes and colors can (even drastically) change during the development process. Also, I tried not to repeat myself (DRY-principle), so, you'll find a sufficient collection of wireframes for this project.
landing page and similar templates within the home app
products page from the products-app
products_details page from the products-app
shopping bag from the bag-app
checkout page from the checkout-app
appointments page from the appointment-app
- please note: I altered the layout a bit because the necessary information for tailoring appointments can be done in a few sentences on the landing page
- so, the appointment page is directly a booking tool for timeslots
- Premium signal: Cinzel is inspired by classical Roman letterforms, which instatnly ready as heritage, craft, and authority. Perfect for a menswear boutique
- Luxury + restraint: the font feels elegant without being flashy. Nevertheless the font shouldn't raise too much attentions because then it would neutralize the effect of elegance. -> decency
- The chosen secondary color/contrast color of golden-yellow fits well on a dark blue, especially since orange is a complementary color of blue. It gives header the perfect luxury/significance look.
- Typography pairing: Cinzel for headings (brand/premium feel) + a clean sans-serif for body text (fast reading, usability)
My color and theme architecture is built on some principles, prioritizing clarity, maintainability, and full control over visual styling across themes - even with Bootstrap.
-
CSS Variables (
:rootand[data-theme])
All theme colors are defined as custom properties, scoped bydata-theme(e.g.,html[data-theme]). This makes theme switching and overwriting instant and modular. -
Structural Specificity without
!important
By using clear scoping via[data-theme],!important-overrides become unnecessary. This eliminates style conflicts and improves maintainability—especially when scaling up. The beauty of this is that[data-theme]creates a higher priority than the bootstrap classes -> that means I can alter the "btn-danger" color with no effort, if I want. It's like an add-on. -
Bootstrap Compatibility by Extension
Bootstrap is not overwritten directly. Instead, custom variables are injected viathemes.cssandthemes.cssto align with Bootstrap’s internal system. This ensures compatibility with future updates and plugins. -
Clear Separation of Concerns
themes.cssholds all visual design tokens (colors, radii, etc.), whilelayout.csshandles structural spacing and layout constants, such as nav-height, general paddings etc. This keeps design logic clean and reusable. -
Cross-Browser Transparency Handling
We avoid problematic#hexAlphasyntax (e.g.,#ffffff80) and usergba(...)for alpha values. Colors without alphas are in hex-method. This ensures consistent rendering, especially in Safari and mobile WebKit engines.
- Scalability – Easily supports future color modes, themes or branding variants without architectural changes.
- Predictability – Reduces CSS conflicts, making the styling layer easier to debug and collaborate on.
- Maintainability – Encourages a consistent design system with minimal coupling between code and visuals. Moreover, other coders could easily adapt and maintain in the future.
- Performance – Theme switching has zero layout cost and minimal DOM operations.
- Professionalism – Clean code structure mirrors industry standards and makes onboarding faster for collaborators.
- High contrast: dark navy background + white/muted text for long-term readability (reduced eye strain, clear scanning). However, blue is generally difficult so read, so, there must be enough contrast to other colors and, more importantly, less saturation of blue (or simply be darker which is perfect for backgrounds)
- Consistent spacing: predictable margins/padding between sections to avoid "visual noise" and improve comprehension. For that, the layouts and the themes (color palettes) are saved in one global file respectively (single source of truth - SSOT): layout.css and themes.css. These two files will be imported to all other css files but they won't import any of the others.
- Responsive behavior: text sizes and layout adapt across breakpoints so content stays readable on mobile and desktop
-
with the above mentioned styles hierachy comes the visual hierarchy.
-
Clear H1/H2 structure: big headline first, supporting text second, actions last (users instantly understand "where they are" and "what to do")
- however, this has limits: repetition and, the more complex the interface is the less space there is for many big headings - eg. the products management page
-
CTA emphasis: primary actions (Shop/book/checkout) use stronger contrast and/or button styling to stand out. Button to attrakt are yellow with blue font. They can afford to stand out (like the
shop now,book nowbuttons). They can also be placed on unusual areas, as long as they attract visually. Other buttons, likecontinueorcheckoutshould still be noticable but not attract to much, as we brought the user to finaly engage with the actual business. But as soon as the user has checked quantities, products, amounts, checked addresses etc. s/he should immediatly see where to go next.
-
Grid-based layout: product cards and forms follow a consistent structure (image -> title -> key info -> price/action), making scanning faster
-
Color as meaning: gold accents highlight key interactive elements and brand moments without overpowering content
- Premium classic tone: Cinzel ü gold accents refernces heritage tailoring/luxury asthetics
- European/German positioning: copy and keywords reinforce "Frankfurt", "made-to-measure-2, "EU shipping" for clear market identity. (IKEA did it very well. Alsmost everyone in the world believes minced meat balls are "typical" swedish - clever marketing positioning)
- Minimal, confident design: avoids clutter, lets product imagery and craftsmanship messaging carry the premium impression. In this case, "confidence" means not placing "buy me"-buttons everywhere and overwhelm the clients with discounts and special offers.
- Professional and reassuring: short, direct copy ("EU shipping", "appointments", "delivery timeframe") reduces uncertainty and builds trust
- Service-oriented: language focuses on fit, consultation, alterations, and guidance (signals expertise rather than pure selling)
- Consistent voice: same style across pages (shop, product details, appointments, checkout) so the brand feels coherent
Our frontend follows a strict mobile-first and progressively enhanced JavaScript approach. This ensures functionality and performance across all devices and bandwidth conditions.
-
Mobile-First Design
Layouts are built from the smallest viewport upward. This guarantees optimal performance and usability on mobile, then enhances for tablets and desktops. Thanks to Bootstrap, this approach nearly happens automatically. -
Progressive Enhancement
Core functionality (navigation, content access, forms) works without JavaScript. Interactive features are layered on top, improving user experience without compromising accessibility. I like to add here: No JS is better than good JS. This is not an argument against JS - it actually is for JS. Use JS for the complicated "in-between" solutions that neither the backend nor html/CSS can solve elegantly. -
Modular JS Components
JavaScript is cleanly structured and scope-safe. DOM manipulation is targeted and event-driven, following best practices to avoid global leakage. Each script gets their own JS file in their own app's static directory. Scripts can become chaotic very quickly, for instance the stripe script. -
Performance-Oriented
No unnecessary libraries are loaded. Vanilla JS is preferred where possible. Event listeners are delegated and optimized for responsiveness. An exception is JQuery. Initially, it was used for stripe until I needed to re-write it to vanilla JS. -
Responsiveness is Testable and Reliable
All breakpoints and flex/grid logic are verified with Chrome DevTools and physical devices.
This approach aligns with modern development standards and ensures consistent behavior across environments—especially in a professional production context. There are still some minor design/layout issues but they are caused by the complexity of collectstatic and deployment.
- appointments[-> booking appointments only]
- bag[-> shopping bag with basic functionalities]
- business_center[-> "the backend" for the shop empoyees to manage products, orders and user rights]
- business center page
- orders management page
- products management page
- user rights page
- checkout[-> the checkout process]
- checkout page
- checkout success page
- home[-> the landing page, newsletter subscription, about]
- landing page
- about page
- impressum
- privacy
- terms and conditions
- my_project [-> the project folder]
- products[-> the product listing as well as the products detail page]
- products page (listing)
- product details page
- reviews[-> rating]
- user[-> profile page, data management, personal appointment management, order history]
- profiles page
- manage appointments page
- edit appointments page
- order details page
global structure
- base.html
- each app has its own app wide base.html. This way each section can have their own headers, footers html
- each app has its own app wide base.css. This way each section can have their own styles, layouts, generic paddings, cardviews etc.
- the base.css will be embedded into the base.hml and all html files of one app extend the base.html
- base.js are rare, as they are limited options to have app-wide, non-site specific and non-global programming logic
- each html has their own 'extra' css file and js, if needed.
- site specific and app-wide static files are saved in the static folder of each app separately to keep overview
- only global static files are saved in the static folder in the root directory (themes.css, layout.css, toast.js..)
- it sound complicated, but in combination with the
collectstatic --noinput --clearit is a very structured and stable "asset management"
- example of app-specific and global base.html
- products
- static/products/ [-> app-specific]
- css/
- base.css [<- global css will be imported here]
- product_details.css [<- global css will be imported here]
- products.css [<- global css will be imported here]
- js/
- product_details.js
- products.js
- css/
- templates/products/
- base.html
- product_details.html
- products.html
- static/products/ [-> app-specific]
- static [-> and global]
- css/
- layouts.css [<- "master" css, this css doesn't import any other css]
- themes.css [<- "master" css, this css doesn't import any other css]
- js
- toast.js
- css/
- products
- includes
- includes make the most sense when they are handled in the global templates folder rather than in app-specific templates folders.
- it happened often that I had to move includes globally, because other (later developped apps) would benefit from them
- such as navigation_bar_desktop, nav_bar_mobile_ nav_bar_desktop_business center, toast_success ...
- Product catalog with filtering and search
- Booking tool with calendar integration
- User profiles with style and measurement data
- Stripe integration for payments
- Admin dashboard
- not yet done (writing this)
- Form input validation
- Booking logic
- Payment validation
- not yet done!
- a custom product admin app with CRUD functionalities to manage products in the store
- email notifications are not in place yet
- SEO is not in place yet
| Key | Name | Type |
|---|---|---|
name |
CharField[100] |
|
slug |
SlugField |
| Key | Name | Type |
|---|---|---|
name |
CharField[100] |
|
slug |
SlugField |
|
description |
TextField |
|
is_active |
BooleanField |
| Key | Name | Type |
|---|---|---|
name |
CharField[100] |
|
slug |
SlugField[100] |
| Key | Name | Type |
|---|---|---|
category |
ForeignKey(Category) |
|
occasion |
ForeignKey(Occasion) |
|
series |
ForeignKey(Series) |
|
name |
CharField[255] |
|
slug |
SlugField |
|
description |
TextField |
|
fabric |
CharField[100] |
|
is_active |
BooleanField |
|
image_url |
URLField[1024] (nullable) |
|
image |
ImageField (nullable) |
|
rating |
DecimalField(6,2) (nullable) |
- please note: the product acts more like a category for the actual product variants which differ by size, color and fit and, technkically by price
| Key | Name | Type |
|---|---|---|
name |
CharField[40] |
|
kind |
CharField[40] |
| Key | Name | Type |
|---|---|---|
name |
CharField[40] (unique) |
|
slug |
SlugField[40] |
| Key | Name | Type |
|---|---|---|
name |
CharField[40] (unique) |
|
slug |
SlugField[40] |
|
hex_code |
CharField[10] |
| Key | Name | Type |
|---|---|---|
product |
ForeignKey(Product) |
|
size |
ForeignKey(Size) |
|
fit |
ForeignKey(Fit) |
|
color |
ForeignKey(Color) |
|
sku |
CharField[50] (unique) |
|
stock |
PositiveIntegerField |
|
price |
DecimalField(8,2) (nullable) |
|
is_active |
BooleanField |
- this is the "actual" product. that, what the customer can order
| Key | Name | Type |
|---|---|---|
user |
ForeignKey(User) |
|
start_datetime |
DateTimeField |
|
end_datetime |
DateTimeField (nullable) |
|
appointment_type |
CharField[20] (choices) |
|
comment |
TextField (nullable) |
| Key | Name | Type |
|---|---|---|
| PrimaryKey | order_number |
CharField[32] (UUID, unique) |
| FK | user |
ForeignKey(User) |
created_at |
DateTimeField(auto_now_add) |
|
updated_at |
DateTimeField(auto_now) |
|
status |
CharField[20] (choice field) |
|
first_name |
CharField[100] |
|
last_name |
CharField[100] |
|
email |
EmailField |
|
phone |
CharField[20] (optional) |
|
address_line1 |
CharField[255] |
|
address_line2 |
CharField[255] (optional) |
|
postal_code |
CharField[20] |
|
city |
CharField[100] |
|
country |
CountryField (django-countries) |
|
total_amount |
DecimalField[10,2] |
|
delivery_costs |
DecimalField[10,2] |
|
grand_total |
DecimalField[10,2] |
|
stripe_pid |
CharField[255] (optional) |
|
original_bag |
TextField (optional) |
| Key | Name | Type |
|---|---|---|
| FK | order |
ForeignKey(Order) |
| FK | variant |
ForeignKey(ProductVariant) |
quantity |
PositiveIntegerField |
|
price |
DecimalField[10,2] |
| Key | Name | Type |
|---|---|---|
| FK | user |
ForeignKey(User) |
| FK | product |
ForeignKey(Product) |
rating |
FloatField |
|
comment |
TextField (optional) |
|
created_at |
DateTimeField(auto_now_add) |
| Key | Name | Type |
|---|---|---|
| FK | user |
OneToOneField(User) |
phone_number |
CharField (optional) |
|
street_address1 |
CharField (optional) |
|
street_address2 |
CharField (optional) |
|
town_or_city |
CharField (optional) |
|
county |
CharField (optional) |
|
postcode |
CharField (optional) |
|
country |
CountryField (optional) |
| Key | Name | Type |
|---|---|---|
| FK | user_profile |
OneToOneField(UserProfile) |
| FK | jacket_size |
ForeignKey(Size) (optional) |
| FK | shirt_size |
ForeignKey(Size) (optional) |
| FK | trousers_size |
ForeignKey(Size) (optional) |
| FK | waistcoat_size |
ForeignKey(Size) (optional) |
| FK | belt_size |
ForeignKey(Size) (optional) |
| FK | preferred_color_1 |
ForeignKey(Color) (optional) |
| FK | preferred_color_2 |
ForeignKey(Color) (optional) |
| FK | preferred_color_3 |
ForeignKey(Color) (optional) |
| FK | fit_preference |
ForeignKey(Fit) (optional) |
| FK | occasion_1 |
ForeignKey(Occasion) (optional) |
| FK | occasion_2 |
ForeignKey(Occasion) (optional) |
| FK | occasion_3 |
ForeignKey(Occasion) (optional) |
- please note: styles are not yet used in the project. It is supposed to be used for email marketing when certain sizes are available again.
- Am I Responsive
- Balsamiq
- Bootstrap v5.3
- Favicon.io
- Chrome DevTools
- Font Awesome
- Git
- GitHub
- Google Fonts
- Render Platform (legacy deployment)
- AWS
- jQuery (it was integrated for stripe - but then i re-wrote it..)
- PostgreSQL
- Summernote
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Landing Page | Load homepage as new visitor | Brand appears premium and stylish | Works as expected |
As a new visitor: I want to view a clean and stylish landing page, so that I can immediately understand the brand’s quality and style
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Landing Page | Load homepage as new visitor | Brand appears premium and stylish | Works as expected |
As a new visitor: I want to see an about page and legal information, so that I can trust the company before making a purchase
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| About & Legal | Access about/legal pages | Transparency builds trust | Works as expected |
As an authenticated user: I want to register for a personal account, so that I can manage my orders and appointments
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| User Registration | Register new user account | Account is successfully created and ready to use | Works as expected |
As an authenticated user: I want to log in to my personal account, so that I can access my profile and saved data
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Login | Log into account | Access to profile and stored user data | Works as expected |
As an authenticated user: I want to reset my password if forgotten, so that I can regain access to my account
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Password Reset | Trigger password reset | Email with reset link is sent | email wont be sent! |
NOTE: An actual email is not been sent to
As an authenticated user: I want to edit my personal data (address, contact, size), so that I can receive accurate recommendations and smooth delivery
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Profile Settings | Edit address/contact/size | Personalized recommendations and correct delivery | Works as expected |
As an authenticated user: I want to see my order history, so that I can track what I have bought and when it will arrive
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Order History | View past orders | Overview of past purchases and expected delivery | Works as expected |
As an authenticated user: I want to book a personal appointment, so that I can get expert advice and fitting services
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Appointment Booking | Book personal appointment | Appointment is scheduled with expert support | Works as expected |
As an authenticated user: I want to manage my upcoming appointments, so that I can reschedule or cancel if needed
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Appointment Management | View/edit upcoming appointments | Appointments can be updated or canceled | Works as expected |
As a buyer: I want to browse suits and accessories by size, category, occasion, fit, fabric, color and collection name, so that I can easily find products that match my preferences
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Browsing | Use filters to explore catalog | Products are displayed according to selected preferences | Works as expected |
As a buyer: I want to view detailed product pages with high-quality images and fabric/ occasion/ color/ size/ fit/ series name/ price information, so that I can make informed purchase decisions
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Details | Open product detail page | Detailed information and images are clearly displayed | Works as expected |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Filter | Apply filters/sorting | Product list updates according to selected options | Works as expected |
As a buyer: I want to search products by name or category, so that I can locate specific items faster
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Search | Use search function | Matching products are shown in search results | Works as expected |
PLEASE NOTE: this user story seems redundant but after a certain time i realized: you dont only want to filter the products, you also want to see information (eg. occasion, series name etc)..
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Ratings | View customer reviews | Displayed reviews give insights into satisfaction | Works as expected |
As a buyer: I want to add items to my shopping cart, so that I can buy multiple products in one transaction
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Shopping Cart | Add item to cart | Product is added and cart reflects correct contents | Works as expected |
As a buyer: I want to edit my cart, so that I can change quantities or remove products before checkout
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Cart Editing | Update/remove item in cart | Cart updates accordingly | Works as expected |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Checkout | Pay via Stripe | Secure payment is completed successfully | Works as expected |
As a buyer: I can see an order confirmation after checkout, so that I can be assured that everything went well
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Order Confirmation | Finish checkout | Confirmation message and order summary are displayed | Works as expected |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Email Confirmation | Check inbox after order | Email receipt with order details is received | Not yet in place! |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Order Tracking | View delivery status | Current shipping and delivery status visible | Works as expected |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Product Review | Submit review form | Review is saved and shown on the product page | Works as expected |
| Feature | Action | Expected Result | Actual Result |
|---|---|---|---|
| Review Editing | Edit/delete a review | Review updates or removal is processed correctly | Works as expected |
- (strictly not a bug) both datamodels "Product" and "Review" have a FloatField for Rating. Only Review should be used
-
checkout process
- solved -> in checkout.views line 99
- dict(settings.STATUS_CHOICES)["created"] # was paid
- solved -> in checkout.views line 99
-
issues in the navigation
- the first name will be displayed in the navbar
- "orders" link works now
-
broken links
- "orders" link in the business center works now
- other links work now, too
-
non-admin users can access product variant page directly
- fixed
-
Code quality maintenance needs PEP8 violation corrections
-
data validation on the product variants page
- implemented
-
data validation on the the profile data
- implemented
-
SEO mechanism missing
- done, see above chapters
-
meta description taghs missing from the application html
- done, see above chapters
-
Deployment instructions for render incomplete
- done, see above chapters
-
include some missing specifications:
- done
-
missing e-commerce business model
- documented above
-
font specifications to complete project overview and design clarity
- documented above
We migrated the project from Heroku to Render.com. This change was driven by the deprecation of Heroku’s free tier and the need for more flexible infrastructure.
- Switched from Heroku to Render’s Infrastructure-as-Code approach
- Recreated all necessary environment variables and secrets within the Render dashboard.
- Connected the Render web service to the GitHub repository with automatic deploys on push.
- Adjusted static file handling and build commands to match Render’s expectations.
- finally, I needed to manually copy my static and media files to the s3 bucket of AWS
- Verified that database migrations and management commands still execute correctly after deployment.
- Set up a custom domain and enabled automatic SSL/TLS encryption via Render’s built-in services.
- No need for separate add-ons for SSL or cron jobs.
- Persistent free tier for small applications.
- Clear and fast deployment logs.
- Git-based CI/CD included by default.
-
Fork the repository (or clone it locally) and make sure your default branch is up to date Project preparation
-
Required root files:
- requirements.txt (must include gunicorn, whitenoise, plus your dependencies)
- Procfile → web: gunicorn <project_name>.wsgi
- runtime.txt (recommended) → e.g. python-3.12.8
- .gitignore (ignore .env, staticfiles/, media/, etc.)
- .env.example (recommended) to document env vars (never commit .env)
-
Configure production settings via environment variables (no hardcoded secrets):
DEBUG=FalseDJANGO_SECRET_KEY=<your-secret>ALLOWED_HOSTS = ['.onrender.com','localhost' ..]includes your Render domainCSRF_TRUSTED_ORIGINSincludeshttps://<your-app>.onrender.com
-
Static / media:
- Use WhiteNoise for static files (recommended)
- Set STATIC_ROOT (e.g. BASE_DIR/ "staticfiles")
- Don't put STATIC_ROOT inside STATICFILES_DIRS
- Media: either keep local for dev or move to S3 in production (optional)
- I recommend to use the existing settings.py, as changing can be time consuming
-
Databases:
- if you use Postgres on Render: use
DATABASE_URL - run migrations of first deploy
- if you use Postgres on Render: use
Render.com registration
- register on https://render.com/
- connect GitHub account there
- If you don't have (access) to a dabases, rreate a Render PostgreSQL database first
Step-by-step: deploy this repo on Render
- fork this repo on GitHub
- in Render:
- create New -> Web service
- Select your forked repo
- Environment: Python
- Configure commands:
- Build commands (very important! Explanation see below):
pip install -r requirements.txt && python manage.py collectstatic --noinput --clear - Start command: `gunicorn <project_name>.wsgi
- Build commands (very important! Explanation see below):
- Set environment variables (unter: Render -> Service -> Environment):
- required:
DJANGO_SECRET_KEY(your secret)DEBUG = False
- Common (depending on features):
DATABASE_URL(Render Postgres)STRIPE_PUBLIC_KEY,STRIPE_SECRET_KEY,STRIPE_WH_SECRETUSE_AWS,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_STORAGE_BUCKET_NAMEandAWS_S3_REGION_NAME- Info: If you can't use AWS, I have saved all product images in
kern_suits/media/products. That way you can choose how to manage data storage
- Info: If you can't use AWS, I have saved all product images in
- required:
- First deploy checklist:
- deploay the service
- Run DB migrations
python manage.py migrate - (Recommended) Create admin:
python manage.py createsuperuser - Now, you are ready to click deploy on render (I recommend to switch auto-deploy on. As soon as you commit, it will be deployed)
Why the build command matters
-
Build command
pip install -r requirements.txt && python manage.py collectstatic --noinput --clear -
This project relies heavily on structured static assets (CSS/JS/images) across apps (e.g. base.css, themes.css, layout.css plus per page JS files)
-
collectstaticis required so Django can serve the correct versioned static assets in production (WhiteNoise uses a manifest + hashed filenames) -
--clearremoves the previous static build before collecting again. This avoids stale/cached assets where older CSS/JS remains instaticfiles/and can trigger errors likeMissing statifiles manifest entry ...- the same applies in DEBUG mode or on local development: As soon as I change js/css/images:
1 the server must be stopped
2 run
python manage.py collectstatic --noinput --clearto really reload the styles/js 3git add .4 if needed, commit 5 start the server again, and all changes are valid now (DEBUG=Falsein the meantime)
- the same applies in DEBUG mode or on local development: As soon as I change js/css/images:
1 the server must be stopped
2 run
-
noinputprevents interactive prompts during Render builds- I recommend this, as long as you work on this project alone (you just want to "get it done", no warnings)
-
Deploy on Render as a Web Service:
- Build command (recommended):
pip install -r requirements.txt && python manage.py collectstatic --noinput --clear- this command is important as this project works with many structured well connected static files, such as base.css, themes.css, layout.css, each html has its own equivalent of .js file (if there is js code for the html).
--noinput --clearwill delete the old static files and overwrite with the new ones. It is helpful because python doesnt overwrite changes in js/css just with collectstatic.
- this command is important as this project works with many structured well connected static files, such as base.css, themes.css, layout.css, each html has its own equivalent of .js file (if there is js code for the html).
- Start command:
gunicorn <project_name>.wsgi
- Build command (recommended):
-
After first deploy:
- Run
python manage.py migrate - (Optional) create admin user:
python manage.py createsuperuser
- Run
- Create a new Web Service
- Connect GitHub and select your fork
- Configure:
- Environment: Python
- Build Command:
pip install -r requirements.txt && python manage.py collectstatic --noinput --clear - Start Command:
gunicorn <project_name>.wsgi
- Deploy → Render will rebuild automatically on every
git push
- Required:
DJANGO_SECRET_KEYDEBUG(set toFalse)
- Common optional vars (depending on features):
DATABASE_URL(Render Postgres)STRIPE_PUBLIC_KEY,STRIPE_SECRET_KEY,STRIPE_WH_SECRETUSE_AWS,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_STORAGE_BUCKET_NAME,AWS_S3_REGION_NAME
- Ensure WhiteNoise is active:
MIDDLEWAREcontainswhitenoise.middleware.WhiteNoiseMiddlewareSTATIC_ROOTpoints tostaticfiles
- Important rule:
- Don’t mix
STATIC_ROOTinsideSTATICFILES_DIRS
- Don’t mix
- If you see:
Missing staticfiles manifest entry ...- Trigger a new deploy and ensure
collectstaticruns and the referenced file exists at the exact{% static %}path.
- Trigger a new deploy and ensure
- First-time deploy needs migrations:
python manage.py migrate
- If you added new models/fields:
python manage.py makemigrationspython manage.py migrate
- Repo contains:
requirements.txt,Procfile, (recommended)runtime.txt - Render Web Service configured with correct build/start commands
- Env vars set (
DJANGO_SECRET_KEY,DEBUG=False, and feature-specific keys) collectstaticruns successfully- App loads on
https://<your-app>.onrender.com
Credits:
References:
- Django docs
- Stripe docs
- Bootstrap 5.3 docs (what a powerful tool)
- Learning material from Code Institute
Media:
- suit01.jpg by Deepak Verma on pexels.com
- suit02.jpg by Pixabay on pexels.com
- suit03.jpg by Tima Miroshnichenko on pexels.com
- suit04.jpg by Antoni Shkraba Studio on pexels.com
- suit05.jpg by Andrea Piacquadio on pexels.com
- suit06.jpg by Lazarus Ziridis on pexels.com
- suit07.jpg by Tima Miroshnichenko on pexels.com
- suit08.jpg by Tima Miroshnichenko on pexels.com
- suit09.jpg by Antoni Shkraba Studio on pexels.com
- suit10.jpg by Pavel Danilyuk on pexels.com
- suit11.jpg by Gustavo Fring on pexels.com
All other images, such as gallery images for the shop, are generated with the AI-based online-tool freepik.com
- Thanks Mo for your guidance (and patience)




























































