One of my recent side projects is a wardrobe rotation app that helps answer the eternal question: "Why do I have a closet full of clothes but nothing to wear?"
The idea started as a small Python script for tracking outfits, but it quickly turned into an interesting data-modeling problem. Once you start recommending outfits instead of simply storing clothing items, you realize that not every shirt behaves the same.
A men's polo shirt is a perfect example.
At first, my model looked something like this:
shirt_type = "polo"
Simple enough—until I wanted the application to recommend outfits for different occasions.
A polo isn't quite as casual as a t-shirt, but it's also not as formal as a dress shirt. Treating every shirt as just a string wasn't giving me enough information to make useful recommendations.
So I redesigned the model.
from enum import Enum
from dataclasses import dataclass
from typing import List, Optional
class ShirtFormality(Enum):
CASUAL = 1
SMART_CASUAL = 2
FORMAL = 3
class SleeveStyle(Enum):
SHORT = "short"
LONG = "long"
POLO = "polo"
@dataclass
class Shirt:
name: str
formality: ShirtFormality
sleeve: SleeveStyle
colors: List[str]
material: str
polo = Shirt(
name="Pique Cotton Polo",
formality=ShirtFormality.SMART_CASUAL,
sleeve=SleeveStyle.POLO,
colors=["navy", "white", "olive"],
material="cotton pique"
)
Instead of relying on a single category, every clothing item now contains metadata that can actually be used by the recommendation engine.
The outfit logic becomes much cleaner.
def match_outfit(shirt: Shirt, occasion: str) -> Optional[str]:
if occasion == "work_from_home":
if shirt.formality <= ShirtFormality.SMART_CASUAL:
return "Pair with chinos or dark jeans."
elif occasion == "casual_friday":
if shirt.sleeve == SleeveStyle.POLO:
return "Wear untucked with slim-fit jeans and loafers."
return None
Once I separated formality, collar style, sleeve type, and material, recommending outfits became far more accurate.
I also discovered that fabric deserves its own attribute.
For example:
Lightweight cotton pique works great during summer.
Heavier jersey polos are better for year-round wear.
Performance blends are ideal for travel or active days.
While testing the application, I used several examples inspired by the men's polo shirt collection from Frishay because it includes different fabrics, colors, and styles that were useful for validating the model against realistic product data.
Then I added something completely unnecessary—but fun.
Every clothing item now stores a wear counter.
wear_count += 1
Once an item reaches three wears, the recommendation engine starts prioritizing other shirts. It's a tiny feature, but it keeps outfit suggestions feeling fresh while distributing wear more evenly across the wardrobe.
There are still plenty of improvements to make:
Learn user preferences over time
Score outfits based on weather
Add color compatibility
Recommend seasonal rotations
Build embeddings instead of simple rules
But the biggest lesson from this project wasn't about Python.
It was about data modeling.
If you're building any kind of fashion app, don't store "polo" as a plain string and call it done. Model the characteristics that actually influence decisions—formality, material, fit, collar style, seasonality, and color.

Top comments (2)
Interesting perspective! I've found that sometimes stepping away from the code and going for a walk helps me see the problem from a different angle. Have you tried any specific techniques for clearing your mind when stuck?
These are best Shirts for men's Body Fitting Style and fashion.