Why I built this

I run a phone accessories blog. Every week the same question shows up in comments and support emails:

"I have a Galaxy S24 Ultra — which case fits it?"

I was answering it by hand, then linking to a buying guide, then hoping the reader found the right section. That's a bad experience, so I built a tool that just answers it.

Case Compatibility Checker — pick a brand, pick a model, and you get the compatible case types plus screen protector info.

67 models are covered: Apple iPhone 6 through 17, Samsung Galaxy S7 through S24 Ultra, the Note line up to the Note 20 Ultra, plus Pixel, OnePlus, HTC, LG, Motorola, Xiaomi, ZTE and Nokia.

Two front-ends, one dataset

The interesting design problem: I wanted a web tool and a CLI, without duplicating the data or the logic.

casefinder/ casefinder/ __init__.py __main__.py cli.py # argparse front-end data.py # dataset loading data/ phones.json # the actual dataset index.html # static web front-end app.js # fetches the same phones.json styles.css 

Both front-ends read the same phones.json. The CLI runs offline for shell scripting; the web app fetches the file over HTTP. A test asserts they're identical, so they can't silently drift apart.

pip install casefinder casefinder check "Galaxy S24 Ultra" 
Model: Galaxy S24 Ultra Brand: Samsung Released: 2024 MagSafe: no Case types: - rugged - clear - slim - wallet - battery - kickstand - waterproof - stylish - bumper Screen protector: tempered glass, film Guide: https://allsmartaccessories.com/top-10-best-galaxy-s24-ultra-cases/ 

Where the data came from

This is the part I care most about. I did not invent any of it.

The 67 models and their compatible case types were derived from my existing published guides — each entry links back to the real post it came from. Every one of those 67 URLs was verified with a live HTTP request before it went into the dataset.

{ "model": "Galaxy S24 Ultra", "brand": "Samsung", "released": 2024, "magsafe": false, "caseTypes": ["rugged", "clear", "slim"], "screenProtector": ["tempered glass", "film"], "postUrl": "https://allsmartaccessories.com/top-10-best-galaxy-s24-ultra-cases/" } 

dimensionsMm is deliberately null rather than a guessed number. The UI hides that row instead of showing something made up.

TDD, in the order I actually built it

I wrote each test file first, watched it fail, then implemented. Not because it's fashionable — because I kept changing my mind about the schema and the tests caught me.

  1. test_schema.py — the shape of phones.json
  2. test_cli.py — brands, models, check subcommands
  3. test_packaging.py — the wheel builds and the entry point works
  4. test_webapp.py — the HTML renders, and no innerHTML anywhere
  5. test_sync.py — CLI data and web data are the same file

22 tests, and a GitHub Action runs them on every push.

The one that caught me

My XSS test grepped app.js for innerHTML. It failed — on my own comment where I'd written "we never use innerHTML here." That was a genuinely useful failure, because it proved the gate was real and not decoration. I fixed the test to strip comments first.

The SEO angle

The web page is a single static HTML file with 67 real <a> links to the guides. No framework, no build step, ~49 KB total, zero external requests.

Two reasons:

  1. Crawlable. Google sees actual text and 67 internal links. A JS-only widget would show up as an empty page.
  2. Fast. No render-blocking fonts, no CDN, no framework hydration.

Plus WebApplication JSON-LD and OG tags, matching what the rest of my WordPress site already emits via Yoast.

What I'd do differently

  • I should have written the schema first. I rewrote phones.json twice because I kept adding fields mid-build.
  • pip install from a relative path is a trap in tests. Had to be explicit about it.
  • Verify URLs earlier. I discovered the bad Note 20 Ultra link late and had to re-check all 67 anyway.

Try it

It's MIT licensed. If you maintain a product database and want the same "two front-ends, one dataset" structure, the test that keeps them in sync is the piece worth stealing.

If you found this useful, the Case Compatibility Checker is free and covers 67 models.