What’s shipping, week by week.
A live log of what we’re building, when it lands, and what’s next. Reverse chronological — newest at the top. Every release tested on real phones against the production API.
Loadouts (“Gear Bag”), club-scoped enrollment hardening, and the move to versioned releases
Five tagged releases shipped the same day, kicking off semantic versioning under a new GitHub Actions release pipeline. Headline feature: the Gear Bag loadout system — pre-configure equipment per division so match registration is a one-tap pull, not a dig through the range bag.
- Loadouts (“Gear Bag”) — list and detail screens, organization picker, division-aware slot validation (firearm / holster / ammo / optics), default loadout per division, slot-constraint preview at registration time.
- PractiScore
.pscimport screen — mobile UI for the.pscimport path that landed on the API last release. Includes a consent gate (“I have lawful authority to share this data”) and writes aScoreAuditLogentry recording source filename and PractiScore match ID. - Equipment screen rebuilt for competitor use — personal equipment now goes through
/shooters/equipment/my/(no club-manager permission required). Caliber became a curated dropdown, serial-number field removed, caliber field hidden for non-firearm gear (holster / belt / etc). - Club-scoped shooter enrollment (security & data hygiene) — match entries can no longer reference shooters from a different club. Hardened in services + serializer + view layers, with a one-shot
audit_cross_club_entriesmanagement command for any historical bad data. - QR contrast fix — match / club / transfer / sync QRs now render hardcoded black-on-white regardless of theme, after a regression where dark mode resolved the QR to invisible-on-invisible.
- Sentry retired — instance was decommissioned. Error boundaries still catch and present errors; we just stopped shipping the SDK and crash-reporting telemetry off-device.
- Android compatibility —
react-native-document-pickerpatched for RN 0.84.1 (deprecatedAsyncTaskremoved). Settings → Manage now navigates into the correct club context.patch-packagewired to apply automatically onnpm install. - Code quality pass — standardized error-message helper across ~70 sites,
useMountedRefhook replacing inline mount-tracking patterns across 15+ components, theme-driven overlay colors, accessibility roles andhitSlopon interactive widgets, type-safety tightening. - CI/CD overhaul — GitHub-hosted runners (ubuntu-latest), composite actions for Node + Android setup, CodeQL security scan, npm-audit, bundle-size + build-metrics tracking, Django backend test workflow, dev-build / promote-to-main / release workflows, branching-strategy doc. Releases now auto-version and auto-tag from
main. - Test coverage push — new pytest suites for matches (24 cases), admin API (36), accounts, shooters, scoring, OAuth, and competitor flows;
pytest-xdistparallelism added. Maestro mobile suite stabilized for Xcode 26 with five new read-only flows and a runner that continues past failures.
snapshot-results v2.6.1 now served from the download endpoint
A small but important deploy: the plugin source had been at v2.6.1 for a while, but the backend download endpoint was still serving v2.1.0. As of 2026-04-30 the Docker build bundles the v2.6.1 zip, the /api/download/wordpress-plugin/ endpoint now returns it, and /api/wordpress-plugin/info/ reports the correct version. Five minor releases of plugin polish that had been queued behind the deploy are now out in the wild for clubs.
- Sport-aware match payload + column-spec from backend — plugin now consumes match-embedded column specs and per-org column visibility, so results tables render the same fields the scoring app captured (with sport-aware wrapper classes and member-id column).
- Generic column-spec-driven results table — new ruleset-aware renderer; meta strip + Register CTA; per-org column visibility settings.
- Recent Results section on club single template, plus polished labels, miss markers, and club nav.
- Optional feature infrastructure: announcement banner toggle + customization docs in plugin settings; banner styles moved to
snapshot-frontend.csswith theme-overridable CSS variables; announcement sync moved to plugin REST + ownsnapshot_announceCPT. - Plugin CSS scoped to snapshot wrappers — no leaks onto the rest of your site’s styling.
- Plugin templates self-center inside theme-provided width; format match_type label on archive cards; link upcoming dates to match pages.
- Save Settings reliability — auto-push toggles now persist (nested-form bug fixed); column-visibility empty-state fixed.
- Backend:
backend/Dockerfile+backend/entrypoint.prod.shupdated so the plugin survives volume mounts;docker-compose.yml+docker-compose.prod.ymlaligned. - Internal cleanup tracker:
docs/TODO_BANKSHOT_CLEANUP.mddocuments the remaining low-priority Bankshot-name remnants in the codebase (docstrings, internal Django app name) for a future refactor pass.
A pile of capability — director-side analytics, equipment validation, classifier tracking, offline volunteer scoring, and an offline-first stack that’s done
A single big release that closes most of the “coming soon” items off the roadmap and adds a director-side analytics layer that wasn’t there before. The equipment system, classifier progression, multi-org alias, and offline volunteer grants all landed together. The offline-first stack matured into something we can stand behind: 14-day mutation queue, local-network HTTP peer sync, NFC tap-to-transfer, encrypted-at-rest queue. Plus a half-dozen director utilities (audit export, match duplication, bulk score lock, batch score import, score-audit screen) that turn a 60-shooter Saturday into a 20-minute scoreboard.
- Equipment system — per-shooter equipment slots (firearm, holster, ammo, optics) tracked on the profile, validated at match registration against the match’s equipment constraints.
- Classifier tracking — competitor-side career screen for rank/classification progression across seasons.
- Multi-org membership + per-org alias — one shooter profile holds per-org aliases.
- League / RuleSet picker in match creation wizard — directors pick league + ruleset per match from the club-default fallback.
- Match Analytics + Operations Dashboard + Score Audit screens — director-side analytics: stage/entry/group analytics, performance trends, career stats, match participant demographics, segmented standings, DQ analysis, sport-data summary.
- Match-level requirement enforcement — toggle per requirement (alias required, equipment constraints, age minimum from DOB, valid membership).
- Match duplication — clone last weekend’s match in one tap; new date, same setup.
- Bulk score lock + batch score import + audit export.
- Offline-first stack matured — 14-day local mutation queue (5,000-operation capacity, encrypted at rest with key in Keychain/Keystore). Local-network HTTP peer sync (port 8847, QR-bootstrap, 30-min sessions). Delta sync with ETags across 9 entity types. Configurable background sync. Embedded scoring defaults.
- NFC tap-to-transfer — NDEF tags carry shooter / match / stage / club / scores payloads up to 8 KB each.
- QR transfer codec — 12 transfer types via compact QR (~2.9 KB chunked).
- Offline volunteer grants — permission grants cache on device.
- Drill goals, Linked-site management, Server-driven onboarding wizard, BLE timer UX polish, Hub-and-spoke HomeScreen, Match Info screen.
- Direct PractiScore
.pscimport / export — the only non-PractiScore app that reads and writes the SQLite format.
Hierarchical org config on the phone, configurable enrollment, richer match data
Parallel to the internal staff config tools, the mobile app got its own Organization → League → RuleSet selection screen. Match directors can now also decide which fields show on the registration form per org or per match.
- Hierarchical org config screen in the mobile app.
- Configurable enrollment fields per organization or per match.
- Official 43 SASS category codes seeded from the 2024 handbook.
- Match-level designation — tag matches as club / sectional / area / national / world.
- Richer match-entry & stage data — power factor, skill class, walk-on flag, stage classifier codes, structured DQ reasons.
- Internal rename: Posse → Group (model layer); UI terminology still adapts per sport.
Any ruleset, no code deploy
The hardcoded Sport model retired. Scoring is now a three-level hierarchy — Organization → League → RuleSet — stored in the database, versioned per year, and composed from eight swappable scoring modules.
One QR every touchpoint, OAuth 2.0 PKCE pairing, and match-day UX polish
Three big bundles landed on the same day: unified QR codes for users / clubs / matches / grants, the Snapshot Results WP plugin jumping to v2.1.0 with OAuth 2.0 PKCE pairing, and a batch of match-day UX improvements (haptics, glossary, toasts, onboarding hints, batch ops). Production hardening for app-store submissions also merged.
Cross-domain stats at a glance
The internal admin surface gained a Dashboard page — single aggregate endpoint returning user, club, match, grant, and audit counts. Live on snapshotscoring.com’s WP admin. Not user-facing; staff-only.
Stage-scoped volunteer access + dedicated scoring forms per discipline
Capability-based permission model with 12 discrete permissions and 3 system roles (Owner, Match Director, Scorekeeper). Match Grant type for stage-scoped temporary volunteer access. Sport-specific scoring UIs (USPSA Hit Factor, IDPA Points Down, Steel 5-string, SASS, 3-Gun per-firearm). Internal /api/admin/ REST surface with bearer-token ServiceAccount auth.
USPSA, IDPA, 3-Gun, Steel Challenge
Snapshot Scoring is no longer SASS-only. Four additional scoring engines shipped alongside SASS, each with full division support, penalty rules, and an in-app rulebook.
Career stats, events feed, club discovery, drill log, season standings
The shooter side of the app became a first-class product this spring: reasons to open the app between matches, and a distribution channel for every club that uses Snapshot Scoring.
QR registration, walk-ups, check-in desk, auto-balance + auto-rotate squads
The full match-day workflow — from pre-match signups through check-in to posse rotation — landed together as a set. No more paper or Excel mediation.
AMG Commander, Shooters Global SG Timer, Special Pie M1A2
Bluetooth Low Energy shot timer integration shipped with three supported devices. Stage times flow directly into the scoring screen — no manual entry, no timer-tape photos.
What’s next
- iOS TestFlight + Android Play Store submissions (builds signed, listings ready, hardening merged).
- Event-triggered push notifications (registration approval, match publish, grant claimed) — infra is live, wire-up pending.
- Cross-club season standings (travel shooters).
- Bullseye / smallbore / PRS / ICORE / IPSC rulesets — email clubs@snapshotscoring.com if your club runs one. The new RuleSet hierarchy makes adding them config, not code.
- Social features for competitors (follow other shooters, activity feed).
- Keycloak SSO for staff access to the WP admin tool.
Build with us.
Have a feature request or a club-specific need? Email us — we read every one, and real-world club feedback drives the roadmap.