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.
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.
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.
UFC.com covers UFC only. ESPN buries fight cards in general sports noise. Boxing, BKFC, and ONE fans have no home at all.
Fighter bios, records, photos, and stats live across Wikipedia, Tapology, and Sherdog — none of it connected or presented for a fan.
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 researchThe 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.
Every piece of information already exists somewhere. The gap is aggregation and hierarchy — one place, surfaced for fans, not for promoters.
Combat sports fans want everything. But cramming it all in kills usability. Every screen had to earn its information — progressive disclosure, not data dumps.
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.
The next event is the most time-sensitive piece of information. It gets the most real estate. Everything else lives below it.
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.
UFC in red, Boxing in purple, PFL in green, ONE in gold, BKFC in orange. Promotion identity from a scan, not a read.
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.
Casual fans care about the main card. Die-hards care about everything. Prelims collapse by default — one tap to open.
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.
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.
Scraped via the itemprop="image" selector with graceful fallback. Real faces make fighter cards feel like a sports app, not a spreadsheet.
KO/TKO, SUB, DEC — color coded red, gold, green. A fan shouldn't have to navigate to understand a fighter's style.
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.
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.
The Wikipedia UFC events list is reliably structured and human-maintained. More stable than scraping UFC.com directly.
Tapology covers MMA, boxing, kickboxing, and Muay Thai across dozens of promotions. The MAJOR_PROMOS whitelist filters to the events that matter.
Full records, fight history, physical stats, and photos — Sherdog is the canonical source for fighter data and the scraper handles their HTML reliably.
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.
Building on a $0 infrastructure budget means confronting the constraints honestly. These were the non-trivial problems worth documenting.
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.
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.
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.
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.
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.
Open on iPhone, tap Share → Add to Home Screen. Installs as a standalone app. Try it now →
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.
Python backend, REST API, multi-source scrapers, CORS configuration, PWA service worker, and production deploy — all built without a framework or starter template.
$0 infrastructure budget forced real engineering trade-offs: scraper resilience, cold start UX, graceful degradation for missing data. Not a greenfield sandbox.
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.
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.