Live PWA — willgraysondesign.com/cutman/app.html ↗
Case Study · Personal Project

Cutman

One app. Every promotion. All the fights. A combat sports dashboard that replaces five fragmented sources with one fan-first interface — designed and shipped as a live PWA.

Role
Design · Engineering
Platform
PWA · iOS · Android
Stack
Python · Flask · PWA
Status
Live
Open Live App
The Problem

Five Apps to Follow One Sport

I follow all of it — UFC, boxing, BKFC, PFL, ONE Championship, Combate, RIZIN. And every single time I want to know when the next event is, where to watch, who's on the card, or what the odds are — I'm bouncing between five different apps. None of them cover all the promotions. None of them surface fighter news alongside the fight card.

There is no hub for combat sports fans that spans all disciplines. So I built one.

Pain Point

No cross-promotion coverage

UFC.com covers UFC only. ESPN buries fight cards in general sports noise. Boxing, BKFC, and ONE fans have no home at all.

Pain Point

Fighter context is scattered

Fighter bios, records, photos, and stats live across Wikipedia, Tapology, and Sherdog — none of it connected or presented for a fan.

Research

What Fight Fans Actually Do

Before designing a single screen, I mapped how hardcore fight fans actually consume combat sports. The pattern was consistent: fans context-switch constantly. They start on Twitter/X to see who's talking about a fight, bounce to Google to find when it's on, open UFC.com for the card details, check ESPN for odds, and land on Reddit to find out what channel the prelims are on. Every fight week is five apps minimum.

"I have six apps on my phone just to keep up with fights. Tapology for cards, Sherdog for fighter records, ESPN for news, and I still end up Googling half of it."

— Pattern from combat sports Reddit / forum research

The second insight came from looking at what the existing apps optimized for. UFC.com is a promotional vehicle, not a fan tool. ESPN serves casual fans — it buries MMA inside a generalist sports feed. Tapology has the data but the interface is built for data, not for fans. Nobody built the product that thinks like a fan first.

Insight

Fans don't need more sources

Every piece of information already exists somewhere. The gap is aggregation and hierarchy — one place, surfaced for fans, not for promoters.

Insight

Density ≠ usefulness

Combat sports fans want everything. But cramming it all in kills usability. Every screen had to earn its information — progressive disclosure, not data dumps.

Screen 01 · Home

The Next Fight, Above the Fold

The home screen has one job: tell you what's coming up and what you need to know before you go deeper. The hero card always shows the next major event — promotion, fighters, date, venue, network, and PPV cost in one glance. Promotion filter chips let boxing fans hide UFC cards instantly. No tapping around to find out what's on.

Hero card takes 40% of the screen

The next event is the most time-sensitive piece of information. It gets the most real estate. Everything else lives below it.

Promotion filter chips, not a dropdown

Boxing fans shouldn't have to scroll through UFC cards. Filter chips let you narrow by promotion in one tap — UFC, Boxing, PFL, ONE, BKFC.

Color-coded promo badges

UFC in red, Boxing in purple, PFL in green, ONE in gold, BKFC in orange. Promotion identity from a scan, not a read.

Screen 02 · Fight Card

Every Fight, Ranked by Importance

The fight card screen surfaces the full event card in a scannable list. Main card at top, prelims collapsible below. Each fight row shows fighters, rankings, and live betting odds inline. Boxing cards — which don't expose per-bout lineup data — show the main event fighters as tappable bio cards with a search bar to pull any fighter's full Sherdog profile.

Prelims are collapsible

Casual fans care about the main card. Die-hards care about everything. Prelims collapse by default — one tap to open.

Boxing events degrade gracefully

Tapology doesn't expose individual boxing bouts the way MMA cards are listed. Rather than show nothing, the main event fighters become tappable profile cards with a fighter search bar below.

Screen 03 · Fighter Profile

Record, Stats, Bio — In That Order

Fighter profiles are scraped live from Sherdog — full record, win method breakdown, fight history, physical stats, and photo. The tab order is intentional: fans want the record first. The win method breakdown (KO/TKO, SUB, DEC) lives on the hero card because a fighter's style is visible in those three numbers before you read a single fight.

Fighter photos from Sherdog

Scraped via the itemprop="image" selector with graceful fallback. Real faces make fighter cards feel like a sports app, not a spreadsheet.

Win method on the hero, not in a tab

KO/TKO, SUB, DEC — color coded red, gold, green. A fan shouldn't have to navigate to understand a fighter's style.

Full fight history in-app

Every result, opponent, event, method, round, and time — scraped live, no stale database. Fans get what they'd find on Sherdog without leaving the app.

Engineering

Scrapers, Flask, and a $0 Deploy

The backend is a Python/Flask API deployed on Render's free tier, scraping fight data from Wikipedia, Tapology, and Sherdog using BeautifulSoup. The frontend is a single-file PWA — vanilla JS, no framework, no build step — hosted on GitHub Pages via a custom domain. Total infrastructure cost: $0/month.

Wikipedia for UFC scheduled events

The Wikipedia UFC events list is reliably structured and human-maintained. More stable than scraping UFC.com directly.

Tapology for cross-promotion fight cards

Tapology covers MMA, boxing, kickboxing, and Muay Thai across dozens of promotions. The MAJOR_PROMOS whitelist filters to the events that matter.

Sherdog for fighter profiles

Full records, fight history, physical stats, and photos — Sherdog is the canonical source for fighter data and the scraper handles their HTML reliably.

RSS feeds for news

9 sources — MMA Fighting, Sherdog, ESPN MMA, Tapology, Bloody Elbow, MMA Mania, ESPN Boxing, Bad Left Hook, The Ring. Merged and sorted by published date.

Python 3 Flask BeautifulSoup4 feedparser Render (free tier) GitHub Pages Vanilla JS PWA flask-cors
Technical Challenges

Real Problems, Real Trade-offs

Building on a $0 infrastructure budget means confronting the constraints honestly. These were the non-trivial problems worth documenting.

Render Free Tier Cold Starts

Render's free tier spins down after 15 minutes of inactivity. First request after spin-down takes 20–40 seconds. The app handles this with a visible loading state rather than a broken experience — a deliberate UX decision to be honest with the user instead of hiding latency behind a spinner that times out.

Scraper Fragility vs. API Reliability

Every scraper is a bet against a site redesign. Wikipedia's structure is stable — it's human-maintained and semantically marked up. Tapology and Sherdog change layouts occasionally. The scraper architecture uses CSS selectors with fallback patterns rather than brittle positional selectors, reducing breakage frequency without over-engineering.

Cross-Origin in a Single-File PWA

The frontend is static HTML on GitHub Pages. The backend is on a different domain. CORS headers on the Flask API + flask-cors solve this, but required understanding how browsers enforce same-origin policy for PWA fetch requests — not a problem that shows up in localhost development.

Boxing Cards Degrade Gracefully

Tapology exposes MMA cards per-bout but boxing events don't have the same structured data. Rather than show a broken card or nothing, boxing events surface the main event fighters as tappable profile cards with a search bar. The app tells the user what it knows, not what it doesn't.

Build Status

Designed, Built, and Live.

Cutman is a fully deployed PWA — installable to your iOS home screen, served from GitHub Pages on a custom domain, with a live Python backend on Render. The entire product, from scraper to UI, was designed and built end-to-end as a solo project.

🚀
Live at willgraysondesign.com/cutman/app.html

Open on iPhone, tap Share → Add to Home Screen. Installs as a standalone app. Try it now →

Frontend
GitHub Pages
willgraysondesign.com/cutman/
Backend
Render Free Tier
cutman-hyf5.onrender.com
7
Screens Built
9
News Sources
5+
Apps Replaced
$0
Monthly Infrastructure
Live PWA · Installable on iOS + Android
For Hiring Managers

What Cutman Demonstrates

Cutman is a solo end-to-end build — no team, no boilerplate, no tutorial. Everything from scraper architecture to PWA manifest to production deploy was designed and shipped by one person. That's the point.

Engineering

Full-stack from scratch

Python backend, REST API, multi-source scrapers, CORS configuration, PWA service worker, and production deploy — all built without a framework or starter template.

Engineering

Real constraints, real decisions

$0 infrastructure budget forced real engineering trade-offs: scraper resilience, cold start UX, graceful degradation for missing data. Not a greenfield sandbox.

Design

Fan-first information hierarchy

Every layout decision prioritized how fans actually consume combat sports — not how promoters want to present them. The research drove the design, not aesthetic preference.

Product

Shipped and maintained

Live at a real domain, installable as a PWA, and actively updated. Not a mockup. Not a Figma file. A product you can open right now.