Built by competitors. Used at the line.
Snapshot Scoring exists because we got tired of paper score sheets, lost timer tapes, and Sunday-night Excel marathons just to publish results from a Saturday match.
The story
This started where most useful software starts — someone shooting an action match got fed up with the way it was being scored.
The first version was a side project to digitize a single Nebraska club’s SASS scoring workflow. It worked. Other clubs noticed. Other disciplines noticed — “can you make it work for USPSA?” became “can you make it work for IDPA?” became “what about 3-Gun?” The codebase grew. The product grew with it.
That product is Snapshot Scoring: a mobile scoring app, a Django REST backend, and a free WordPress publishing plugin — built for the people who actually run action shooting matches in the dirt. Twelve sports scored by one configurable engine, composed from eight modular scoring primitives, one match-day workflow, and a publishing plugin (snapshot-results) that puts every locked match on your club site when you press Sync Now in WordPress, or on its own with Auto-Push on.
Every feature we ship has to pass one test: does it save the director ten minutes, make the scorekeeper faster, or give the competitor a reason to open the app on a non-match-day? If not, it doesn’t ship.
What we won’t do.
Building a scoring app for a niche, opinionated sport requires saying no to a lot of things. Here’s what we’ve already said no to.
No spreadsheet exports as the source of truth
The match lives in the app and the database. CSV is for sharing — never for re-entering data later. If the workflow needs Excel, the workflow is broken.
No setup required for official rules
Every supported sport ships seeded with its official categories, divisions, and penalty weights. Clubs shouldn’t have to set up rules somebody else wrote. If you run a house variant or a local league year, email us — we add it to the shared catalog and your mobile app picks it up on next sync.
We never paywall scoring accuracy
The scoring engine is the product. We will never ship a crippled free version and charge for correctness. Competitors always use the full app for free; clubs and circuits pay a flat yearly price to host and publish.
No bright UI in direct sun
High-contrast, oversized targets. Every screen optimized for outdoor range conditions — not a dim conference room.
No ad-supported anything
The app will never serve ads, sponsored content, or promoted firearms. Real shooters use this to score real matches; we’re not turning their attention into an asset.
No locking your match data
Your match data is yours. Export a match as CSV, PDF, or awards certificates from the Results screen any time, and there is a JSON match export on the API for third-party integrations. We’re not building a moat with your data.
No mystery state
Every mutation — a score edit, an ownership transfer, a role change, a staff admin action — lands in an append-only audit log with actor, timestamp, IP, and before/after deltas.
No vendor lock on your site
The WordPress plugin is GPL-licensed and free. Connect your own site via OAuth 2.0 PKCE — we never host your club site. Styled templates ship out of the box; override them via the standard WP template hierarchy when you want to.
How it’s built.
For the engineers reading: the stack, in case it matters to your evaluation.
React Native
iOS & Android from a single TypeScript codebase. Native build, not a wrapped web view. BLE timer adapters in TypeScript, NFC pairing where available, QR scanner via react-native-camera-kit. Hub-and-spoke HomeScreen scales with shooters who hold multiple roles (Compete / Score / Manage).
Django REST + PostgreSQL
Twelve sports on fourteen scoring presets, one configurable engine, eight modular primitives (time_plus, hit_factor, points_down, raw_time, drop_worst, power_factor, bonus_targets, detailed_misses). Organization → League → RuleSet hierarchy in the database, versioned per year. JWT auth for mobile; OAuth 2.0 provider for the WordPress connection; scope-gated ServiceAccount bearer tokens for admin/support.
Entry requirements
Shooters record their firearms once on their profile; match directors set six per-match toggles — alias, date of birth on file, minimum and maximum age, weapon type, and caliber — and the app refuses an ineligible entry at sign-up, naming the rule that failed, before it lands on the line.
WordPress plugin
Free GPL-licensed plugin for any club’s WordPress site. OAuth 2.0 PKCE connection, with the OAuth client secret held AES-256 encrypted in the site’s options table, custom post types with styled out-of-box templates. Multi-site management — one director account connects many sites. Press Sync Now in WP admin to publish a locked match, or turn on Auto-Push and locked matches publish themselves; templates overridable via the normal WP hierarchy.
Append-only audit log
Every destructive operation — score edits, unlocks, ownership transfers, staff actions — captured with actor, timestamp, IP, and before/after deltas. The Score Audit screen surfaces every score edit per match, filterable by entry, stage, user, action, and date.
Maestro E2E
Maestro end-to-end tests run on real iOS and Android hardware against the production API before every release, so breakage shows up here rather than at your match. App screenshots on this site come out of that same pipeline — real app, real backend, no mockups.
Offline-first sync stack
Independent mechanisms compose the offline story. (1) 14-day local mutation queue, 5,000-operation capacity, payloads obfuscated at rest with a key in the device Keychain / Keystore, mutex-protected against concurrent writes. (2) Background sync — auto-sync on foreground, configurable interval, WiFi-only mode, low-battery skip, pause/resume, exponential retry up to 5 minutes. (3) NFC tap-to-transfer with NDEF tags up to 8 KB carrying a match’s score bundle. (4) QR transfer codec across 12 payload types, chunked for larger data.
Embedded scoring defaults
Sport rules cached on device at install time. A freshly-installed phone can score offline immediately — no first-load round-trip, no “please connect to download rulesets.” Club roles and their permissions cache on device too, so a scorekeeper can work a remote bay with no signal.
Server-driven onboarding
First-run flow lives on the backend, so improvements ship without an app update. Walks new shooters through profile, membership numbers, follow-a-club, and notification preferences. Update the wizard once on the server; every install picks it up on next launch.
Multi-org schema
One shooter profile holds SASS, USPSA, and IDPA membership numbers and per-org aliases. Scores from any sport auto-link to the right ID at the right organization. Travel shooters across three disciplines stop showing up as three duplicates with three classifiers.
Director analytics layer
Match Analytics, Operations Dashboard, and Score Audit screens give directors everything from segmented standings and DQ analysis to match participant demographics. Performance trends + career stats roll up across every match a club has run.
Infrastructure under our control
Django + Postgres on servers we run ourselves (no serverless black box). TLS everywhere. Deploys go through review; production writes route through audit-logged admin paths; there’s no “quick fix in the shell.” Releases move through deploy rings — every merge ships to edge, tagged releases promote through a beta ring (TestFlight / Play internal) to production, one release behind on purpose. Each ring reports its own health, and the status page shows which version production and beta are running plus rolling uptime.
Nearly 10,000 automated tests
Nearly 10,000 automated tests run in CI before every release — more than 3,400 backend (Django/pytest) and 6,200 mobile (React Native/Jest) — with coverage floors that can’t regress.
Bring your club in before the iPhone app lands.
Founding status is open until the iPhone app is on the App Store: run a match with us before then and your club keeps full access free for life. Every other club runs on a $20/year seat, with no per-shooter or per-match fees. If you would rather ask something first, we read every email, and the team is small enough that you’ll get a response from someone who can actually do something about it.