Tommy Chapman
  • Archive

    Reflections on production, development, and concept web sites

  • About

    Who is this guy, what's he in to, and how you can get in contact with him

  • Blog

    Bits and bytes, things I like, but also things I don't like as much

© 2026 Thomas Chapman
169
SNKRTRKR
    • Live
    • Development
    • Design
    • 2026
    • https://snkrtrkr.app
    • Swift
    • Node.js
    • MySQL
    • Playwright
    • Next.js
    • Adobe Illustrator
    • Adobe Photoshop

SNKRTRKR is a universal iOS and macOS app for monitoring Nike sneaker prices across Australian retailers. It watches for price drops, surfaces historical lows, and keeps track of what you own.

Origins

I kept missing sales. I'd check Nike, then Foot Locker, then JD Sports, then forget what I'd seen on the first one. There was no single place that told you whether the price you were looking at was actually good. I built SNKRTRKR to solve that for myself, and it grew from there.

Problem

Nike and its retail partners don't make it easy to compare prices across storefronts. A shoe listed at full price on one site might be 40% off on another, and there's no way to know without checking each one individually. Knowing whether a price is genuinely good requires history, something none of the retailers expose.

SNKRTRKR aggregates that data and presents it in one place, with enough context to actually make a decision.

c6b79472-eb4f-4748-a831-6f8da83f4b1fc6b79472-eb4f-4748-a831-6f8da83f4b1f
17f5a741-3471-4277-bc93-b67a47f1a5bd17f5a741-3471-4277-bc93-b67a47f1a5bd

Architecture

The app is built in SwiftUI using Swift 5.9's @Observable macro, which simplified state management considerably over the older ObservableObject pattern. A single view model manages fetch lifecycle, loading states, and stale-fetch cancellation through a generation counter—each new request increments it, and any response from a prior generation is discarded.

User data–watched styles, size preferences, the personal collection–syncs across devices through a custom @CloudStorage property wrapper I wrote that writes simultaneously to UserDefaults and NSUbiquitousKeyValueStore. Collection photos go to iCloud Documents, compressed and resized before saving.

The same codebase runs on macOS. Adapting it meant swapping a few platform-specific APIs—UIImage for NSImage, .glassEffect() for .regularMaterial, a menu bar shortcut for manual refresh—but the architecture didn't need to change. SwiftUI largely delivered on its promise there.

The API I built to drive it runs from a Docker container and gently scrapes Nike, Foot Locker, JD Sports, and Culture Kings on a schedule and aggregates results by style code, grouping the same shoe across multiple sources. The API exposes a full catalogue endpoint and a slim watch endpoint for background fetches on only the styles a user cares about.

Scraping takes time, so the server returns a warming flag when fresh data isn't ready. The app handles this gracefully–showing stale data immediately and polling silently until a fresh response arrives.

Notifications

iOS background app refresh runs on a 15–60 minute interval. When it fires, the app loads a snapshot of the last-known prices, fetches only the user's watched styles, diffs the result, and fires local notifications for drops or newly discounted items.

Early on I noticed retailers occasionally oscillate between in-stock and sold-out states within the same day. Without a safeguard, a single pair of shoes could generate a dozen alerts overnight. I added a 24-hour cooldown on sale notifications to prevent that.

Collection

The collection tab is a personal inventory for the shoes you own. You can log a style manually, attach a photo, and record which sizes you have. But the more interesting path is through the scanner.

DataScannerViewController from VisionKit handles live text recognition against the camera feed. Rather than scanning barcodes, it reads printed text and runs it against a regex that matches Nike style codes in both formats: alphanumeric like AV3595-002 and numeric like 604133-139. Point your camera at a receipt or a tag, it finds the code, matches it against the catalogue, and adds the style to your collection. No typing.

The didFind flag ensures it fires exactly once per scan session. A guard at the call site checks scannerSupported before the scanner UI is ever shown, keeping it iOS-only without polluting the shared codebase. The whole thing is about 50 lines.

Photos are stored in iCloud Documents alongside the rest of your data, resized and compressed before saving.

0e9b10e8-87ea-4bb1-bbdf-f9c39f63ad200e9b10e8-87ea-4bb1-bbdf-f9c39f63ad20

Monetisation

SNKRTRKR is free to download. Watching up to three styles and browsing the full catalogue are available to everyone. Push notifications and adding more than three styles to your collection require a one-time purchase.

I built the app for myself and open-sourced the problem-solving. The purchase is for people who want to use it seriously, and the passive income offsets the cost of keeping the backend running.

9b1b0d27-d337-4328-a53a-fbad00f8f4e89b1b0d27-d337-4328-a53a-fbad00f8f4e8

Branding

As this is a real product, live on the App Store, which I'm promoting to friends through Instagram, I had to fulfill some requirements. My first instinct was to borrow Nike's own branding; however, I hear there are rules and stuff. So, I went abstract, and through some light iteration, I've arrived at a result where I've reduced the Tuned Air logo to its simplest form and borrowed my portfolio site's own font for marketing materials.

926ea124-877e-4304-8418-6ecc8cd8b89d

Related

Deploy create-react-app to DigitalOcean Droplet with SCP
Blog Entry

Replacing Netlify with a free and powerful alternative.

Multi-Process Life
Blog Entry

Why use a single thread when you can use multiple.

With 2020 vision
Blog Entry

Musings on remote server management, the recycle bin, rookie mistakes, and whether or not it's worth buying for backup addons

npm-check-updates
Blog Entry

The best simple tool for keeping your package.json fresh

Tom Chapman: Photographer
Archive Item

An atypical photographer's portfolio with features other photographers wish they had. A beautiful blend of magazine spreads and grid-based albums, with a pinch of data-rich tools.

Braytech
Archive Item

Braytech is a third-party companion app for Bungie's Destiny which enables players to track their progression and find answers to their queries through various views which mimic and elevate Destiny's own interfaces with insightful features and additional curated data.