Inspiration

When I took up sport shooting, I realised there was no modern and up-to-date app leading the market, and I saw a chance to solve not just one problem but a whole set of them. Especially with new licensing rules coming into force next year in my home country, Sweden, which call for a digital solution that doesn't exist yet:

  • You still do the work yourself. Most scoring apps make you tap in every hit by hand. Shooter finds the holes in a photo for you, then works out your sight adjustments, builds a training programme tailored to your shots, logs your activity for both your club and your licenses, and notifies you when it's time to act.
  • Narrow coverage. Existing apps support a handful of targets. Shooter covers 179 target faces across ISSF and national federations. Detection runs fully offline on your phone, with AI as a backup for unsupported targets. Every AI-scored photo then helps improve the offline engine, fully autonomously. The more people shoot, the smarter it gets: a self-improving machine.
  • New rules, no tools. New licensing rules require shooters to prove regular activity, and clubs and range officers now have to record and confirm it. No app handled either side, so Shooter tracks your activity and license renewals, and gives clubs and range officers the tools to check shooters in and keep the records.
  • Everything in one place. Your own shooting badges and your club's badges, your activity and your licenses. Every log comes to life in graphs, heat maps and detailed statistics.
  • Hard to use. Many apps on the market make simple tasks needlessly complex. I spent a lot of time making Shooter simple and fast, so recording a session takes seconds, not minutes.

What it does

Shooter turns a photo of a paper target into an exact score, then into training.

  • Scan — photograph the target; every shot hole is detected and scored in seconds, fully offline on the device, with an optional AI mode for (yet) unsupported targets.
  • 179 target faces — ISSF and national federation disciplines.
  • Improve — a heat map across sessions that tells you how many clicks to adjust your sights, an analysis of your grouping, a training programme built around your own shots, and badges that track your progress.
  • Around the sport — a weapons log that reminds you before a license renewal, a club tab with check-in and range-officer tools, and PDF reports.
  • Bring your history — import your sessions from TargetScan, so years of shooting aren't lost when you switch, and import your federation's badge system in one tap. Backup & restore keeps it all safe when you change phones.
  • Scope Mode — mount your phone on your spotting scope and score every shot live from the firing line. Fire, press a Bluetooth remote or the shutter, and the app spots the new hole, scores it and reads the score aloud. No walking to the target, and you never have to take your eye off the shooting.

How I built it

  • React Native + Expo with Expo Router and Tamagui, organised with Feature-Sliced Design in a pnpm/Turborepo monorepo.
  • Computer vision in C++: an OpenCV pipeline exposed through a Turbo Module — preprocess → find the target → correct perspective → normalise → detect shots. Shot detection is multi-phase (HSV saturation, gradient voting, top-hat morphology and contrast analysis).
  • Normalised geometry: every distance is a ratio of the detected target radius, so scoring doesn't care about camera distance. Scoring follows ISSF gauge rules — a hole counts for the ring its edge touches.
  • Local-first data: SQLite with Drizzle ORM; your history never needs a server.
  • RevenueCat runs monetisation on both stores: a Pro subscription and consumable credit packs for AI scoring. Webhooks keep a server-side paid flag in sync, and RevenueCat's PostHog integration ties purchases to product analytics.
  • A small Next.js backend on Vercel secured with Apple App Attest and Google Play Integrity instead of user accounts.
  • An admin app (Next.js) that runs the machine behind the scanner: annotating real target photos as ground truth, visualising every step of the detection pipeline, and an auto-tuner that re-tunes the detector per discipline whenever that improves the score. AI-scored photos surface there as candidates for the offline engine. It also manages the catalogue of targets, ammunition, federations and badges, and tracks business metrics.

Challenges

  • Offline detection is hard. Finding every shot hole on-device, with no server and no AI, takes an advanced multi-stage pipeline and a lot of real target photos to train and benchmark against. It's worth it: offline scans are instant, work at any range with no signal, and don't depend on AI or its costs.
  • Rules that aren't written yet. The new licensing requirements arrive next year, but exactly how shooters, clubs and range officers are supposed to prove and record activity isn't fully defined. I've had to design for a target that is still moving, and keep the model flexible enough to follow the final rules.
  • Every target, not just a few. Most apps support a handful of targets. Shooter aims to handle all of them, 179 target faces across federations and countries, each with its own ring geometry, scoring rules and quirks for the detector.
  • Meaningful training, fully offline. Tailored training programmes have to turn a shooter's own shot history into sessions that actually help, and then track whether they do. All of it runs on the phone without a server, so every bit of that logic lives in the app itself.

What I learned

Computer vision is 10% algorithm and 90% benchmark: without annotated fixtures and a regression check on every change, "better" is just a feeling.

What's next

  • More targets offline. Hopefully, every target face in use will get full on-device detection. The AI backup keeps training the offline engine, so the list of targets that need no AI and no signal keeps growing.
  • More for clubs. Taking the club tools from experimental to complete, in step with the final licensing rules, and building out what clubs and range officers need to run their activity from the app.

Built With

Share this project:

Updates

Submission history