The Problem
The bra industry's standard sizing method — measure your underbust, add 4 inches, that's your band — is wrong. It was designed in the 1930s when fabrics had no stretch, and it systematically puts people in bands too loose and cups too small. The community at r/ABraThatFits has known this for years, but their knowledge exists scattered across tens of thousands of posts.
I wanted to build a tool that combines real measurement math with community intelligence from 45,000+ posts. Not a lookup table — an algorithm that understands that two people with identical measurements but different breast shapes need different sizes.
The Approach
The sizing algorithm rejects the +4 method entirely. Band size rounds the snug underbust to the nearest even number via roundToEven(), clamped to 26–48. But the cup calculation is where it gets interesting.
Three bust measurements capture the same tissue from different angles: standing (compressed by gravity), leaning (maximum projection, tissue hangs freely), and lying (tissue spreads laterally). The key insight is that these three measurements should be weighted differently based on breast shape.
Projected shapes (tissue extends forward):
bust = (standing + leaning×2 + lying) / 4
// leaning at 2× because it's the most telling
Shallow shapes (tissue stays close to chest wall):
bust = (standing×2 + leaning + lying) / 4
// down-weight lean — it would overpredict volume
Moderate:
bust = (standing + leaning + lying) / 3
Safety cap for extreme projection:
if (leaning - standing) > 2.5":
bust = (standing + lying) / 2 + 1The safety cap prevents over-sizing from extreme lean measurements — if someone's leaning bust is 3+ inches more than standing, the lean measurement is likely overpredicting actual in-bra volume.
The style matching engine layers five scoring dimensions to rank every bra in the database:
Measurement proximity (max 0.25 points) — compares the user's calculated cup depth and width against brand-specific measurements, weighting depth 1.67× over width (cupDepthDiff*0.05 + cupWidthDiff*0.03).
Projection matching (0.15 points) — scores how well a style's depth-to-width ratio matches the user's shape profile.
Root width scoring (0.08 points) — compares expected root width at the user's cup size (4.5 + 0.3 * cupIndex) against actual measurements.
Tag affinity (up to 0.24 points) — rewards styles with construction tags matching the user's shape. Projected shapes prefer seamed, unlined, balconette; shallow shapes prefer molded, t-shirt. Each match adds 0.06, each mismatch subtracts 0.04.
Data quality bonus (0.08 points) — styles with more measurement samples (10+ and 30+ thresholds) score higher because the data is more reliable.
The community intelligence layer processes a 16MB search index of 45,000 posts. The search uses synonym expansion (90+ mappings — "spill" expands to spillage/overflow/quadboob) and multi-field scoring: tag match gets 3 points, title gets 2, snippet gets 1, plus quality bonuses for post length and comment count. Community insights are pre-bucketed by band/cup range (32-34|D-DD) so each user sees sentiment data specific to their size neighborhood.
The fit check solver works backwards from symptoms. It takes a current bra and a list of problems, then applies incremental adjustments with conflict resolution. Band too loose → down 2, up 1 cup (volume conservation). Gore doesn't tack → up 1 cup. The tricky cases: straps falling but band feels fine → the band is actually too loose (counter-intuitive), so down 2 and up 1. When signals conflict, explicit priority rules resolve the contradiction.
The Hard Parts
Shape-aware cup calculation. Same measurements, different sizes. Two people with identical bust and underbust numbers but different tissue distributions (projected vs. shallow) genuinely need different cup sizes. Building this into the algorithm required understanding the biomechanics — projected tissue creates more forward volume per inch of circumference than shallow tissue.
The three-measurement approach with shape-dependent weighting captures this, but calibrating the weights required working through hundreds of real fitting scenarios from the community data. The 2× leaning weight for projected shapes and the 2.5-inch safety cap emerged from testing against the 231 documented size transitions in the dataset — cases where someone reported both their old (wrong) size and their new (correct) size.
Multi-issue fit solving. Real fit problems are rarely single-cause. Straps falling could mean the band is too loose (sizing issue), the straps are too wide-set (shape issue), or the cup is too small (weight pulls everything down). My solver handles this through priority ordering — band corrections first, then cup adjustments, then shape-based style recommendations.
The hardest case is when signals contradict. User says the band feels fine but it's riding up. Riding up means it is too loose — gravity pulls the front down, the back rides up as a lever. The solver needs to override self-reported comfort with diagnostic evidence. This kind of domain-specific reasoning is what makes it more than a lookup table.
56 brands, no consistent measurement system. A 34D at Panache has different cup depth and wire width than a 34D at Natori. The size label is almost meaningless across brands. The conversion engine uses a weighted distance metric: abs(cupDepth_diff)*2.5 + abs(cupWidth_diff)*1.5 to find actual measurement matches, ignoring labels entirely. This required aggregating 500,000+ individual measurement data points from the community into style-measurements.json — 5MB of structured measurement data across every brand and style.
The deduplication logic (max 2 styles per brand, 15 total results) and the acceptance threshold (reject matches with distance > 3) prevent the results from being dominated by a single well-documented brand or returning false-confidence matches.
What I'd Do Differently
The sizing algorithm is rule-based — handcrafted weights and thresholds calibrated against community data. A trained model could learn the mapping from measurements + shape → size from the 231 documented size transitions. The challenge is that the training data is biased toward people who discovered they were in the wrong size — the model would need careful calibration against known-correct fittings to avoid systematically over-correcting.
I'd add a feedback loop where users report whether recommendations actually fit. Right now the system is one-directional — measurements in, size out. Accumulating fit feedback per brand and style would let the scoring weights self-calibrate. If users consistently report that Brand X's 34G runs small, the system should learn to bump up recommendations. The profile system with fitFeedback array is already designed for this — it stores brand, style, size, and rating — but the scoring engine doesn't consume it yet.
The aesthetic goal integration could be deeper. Right now it re-ranks matches by tag affinity (0.55 * fitScore + 0.45 * goalAffinity), but it doesn't reason about shape-goal interactions beyond a fixed bonus table. A projected shape looking for lift benefits differently from a shallow shape looking for lift — the physics of tissue support are different, and the style recommendations should reflect that at a more granular level than the current ±0.1 shape boosts.