🔴 Release v2.286.4
⭐⭐⭐ Complex • 34 commits • 269 filesv2.286.4 is a massive release featuring Receipt Scanning 2.0 deduplication (fraud prevention), Action Webhooks (per-action event integrations), Shopify Refer-a-Friend widget, configurable widget loading states, and significant performance improvements across the API. Six major features ship alongside 20+ bug fixes and optimizations — this release unlocks integrations that weren’t possible before and strengthens fraud resilience for receipt-based actions.
What’s New
- Receipt Scanning 2.0: Strict Deduplication – Reject duplicate receipt submissions via four content-based signals (file hash, perceptual hash, receipt ID, store+date+total) with cheap signals running before the expensive GPT-4o call to eliminate fraud
- Action Webhooks – Fire webhooks on any action completion (not just challenges) and configure them by specific action ID, unblocking integrations that react to receipt scans, video completions, or other individual actions
- Refer-a-Friend Shopify Widget – Embedded storefront block allowing merchants to showcase referral rewards directly on their Shopify store
- Configurable Widget Loading State Design – Customize how the loyalty widget displays while loading with different layout styles, animations, colors, and messaging
- Theme Editor Accessibility & Real-Time Sync – Improved keyboard navigation, real-time iframe synchronization, default community selection, and undo functionality for theme customization
- API Performance Surge – Eliminated N+1 queries in reward-entries, parallelized sequential database calls, optimized integration endpoints with 4+ indexing improvements
- Leaderboard Privacy Enforcement – Fixed identity masking on leaderboards when “hide identities” is enabled so usernames never leak
- Admin Auth Security Fix – Moved access token generation from session to JWT callback for more secure token handling
- Font & Styling Improvements – Swapped font to FreightSansCndPro-Book for better typography, fixed leaderboard card colors, stopped widget styles leaking to community pages
- Observability Overhaul – Consolidated BetterStack configuration across all applications for unified monitoring and error tracking
Apps Updated
User App
✓ Updated - Performance, styling, and theme fixes
API
✓ Updated - Receipt dedup, webhooks, 7+ optimizations
Admin
✓ Updated - Widget config, webhooks UI, theme editor
MCP Server
✓ Updated - Observability enhancements
Shopify
✓ Updated - Refer-a-Friend widget block
Games
— No changes
Detailed Changes
Major Features
Receipt Scanning 2.0: Strict Multi-Signal Deduplication (NUDJ-5541, NUDJ-5542)
Receipt scanning now rejects duplicate submissions before they incur GPT costs using a multi-layered approach:- File Hash Matching – Exact binary match of the image file
- Perceptual Hash Similarity – Visual similarity using Hamming distance (configurable threshold, default ≤6)
- Receipt ID Deduplication – Receipt ID string extracted by GPT (after initial analysis)
- Store + Date + Total Triangulation – Same merchant, purchase date, and total amount (temporary hard reject pending PR3)
- Cost optimization: cheap signals (hash-based) run before the OpenAI call, eliminating ~$6/month in duplicate submission costs (100k receipts/month @ 2% duplication)
- Per-community scoping: receipts in community A don’t block identical receipts in community B
- Configurable window: admins set dedup history depth per action (default 90 days, range 1-365)
- Privacy-preserving: users see generic “already submitted” message; internal logs track which signal triggered for observability
- New
dedupWindowDaysfield on receipt-detection action configuration - Four new database indexes for efficient lookups
- Structured BetterStack logging on every dedup hit for fraud monitoring
Action Webhooks (NUDJ-5587)
Webhooks now fire on individual action completions, not just challenge completions, enabling integrations that react to:- Receipt submissions (with dedup signals)
- Video completions
- Survey responses
- Any custom action type
- Fire webhooks on
ActionCompletionevents per-action granularity - Use the existing include/exclude entity filter by
actionIdto target specific actions - Full parity between API webhook events and admin event picker (customer-facing events only; internal Shopify/Auth events remain hidden)
- No behavior change for existing challenge-completion webhooks
- Event picker now shows “Action Events” category alongside “Challenge Events”
- New “Shopify Events” category exposes internal integration events for completeness (read-only reference)
- Free-text field to specify action IDs to include/exclude
Refer-a-Friend Shopify Widget Block (NUDJ-5453)
New Shopify Theme App Extension widget block for merchants to embed a Refer-a-Friend panel directly into their storefront:- Displays referral rewards and instructions inline
- Customers copy referral link from the widget
- Integrates with existing Nudj referral system
- Fully themed to match community branding
- Works alongside the floating action button
Configurable Widget Loading State Design (NUDJ-5558)
Admins can now fully customize the loading state design that users see while the widget initializes: Customization Options:- Layout Styles – Skeleton card layout, shimmer animation, plain background
- Colors – Custom hex input for background color
- Animation – Toggle animation on/off, choose animation style
- Content – Custom header text, logo display toggle, community name display toggle
- Card Count – Configure skeleton card count (1-5 cards)
- Typography Presets – Font pairing presets for header and body text
- Real-time iframe synchronization shows changes instantly
- Save & reload persistence ensures settings stick
- Comprehensive keyboard navigation for accessibility
- 20+ edge case tests for robustness
Theme Editor Improvements (NUDJ-5556)
Enhanced theme editor with better UX and accessibility:- Keyboard Navigation – Full tab/shift+tab support for form controls
- Real-Time Iframe Sync – Preview updates instantly as you adjust colors (no page refresh needed)
- Default Community Selection – Theme editor opens with a community pre-selected
- Undo Functionality – Undo recent changes without losing work
- Accessibility Improvements – Better focus indicators, ARIA labels, keyboard shortcuts
Performance Optimizations
N+1 Query Eliminations
- me.reward-entries endpoint – Eliminated N+1 in reward details fetching
- me, me.rewards, games.:id endpoints – Optimized integration endpoints for better throughput
- Challenge completion flow – Parallelized sequential database calls
Database Indexes
Four new compound indexes for receipt deduplication lookups:- File hash index with location + org + community scope
- Perceptual hash index with createdAt for window filtering
- Receipt ID index for quick dedup checks
- Triangulation index (store + date + total) for complex dedup
Parallel Database Operations
Sequential find+count operations parallelized in action endpoints, reducing total database round trips by 40-50%.Bug Fixes & Quality
User App
User App
- Leaderboard Identity Masking Fixed – Usernames no longer leak when “hide identities” is enabled on leaderboards
- Leaderboard Card Colors – Fixed background color application to match primary theme variable
- Widget Color Isolation – Stopped widget styles from bleeding into community page elements
- Font Typography – Swapped Freight Sans Bold with FreightSansCndPro-Book for improved consistency
- XP Step Opacity – Increased tap-to-continue opacity on XP earn step for better visibility
- Available Challenge Count – Show available challenge count in navigation and empty state when no challenges available
- Error Capture Normalization – Improved non-Error capture handling in error tracking
API
API
- TRPCError Code Preservation – Fixed error code loss in events.claim catch block
- MongoDB Connection Consolidation – Moved all admin app MongoDB connections to packages/database (fixes production MongoServerSelectionError)
- Action Participation Indexes – Added compound indexes for efficient participation lookups
Admin
Admin
- JWT Authentication – Moved access token generation from session to JWT callback for enhanced security
- Featured Card Toggles – Replaced button-based featured card toggle with Switch component for clearer UX
- Memory Game Images – Generated IDs and alt text for new memory game card images (improves accessibility)
Design System
Design System
- Achievement Description Rendering – Fixed action component achievement description display in design-system components
Observability
Observability
- BetterStack Configuration – Comprehensive configuration overhaul for unified error tracking, structured logging, and performance monitoring across all apps
- Perf Analysis Hub – New autonomous agent skill for analyzing slow API procedures
- Bug Triage Automation – Enhanced automated error categorization across BetterStack
Technical Details
Receipt Deduplication Architecture
The dedup system runs in two phases with intelligent cost optimization: Phase 1 (Pre-GPT): Hash-based signals on the raw image- File hash check (SHA256) – $0 cost, immediate
- Perceptual hash check (phash + Hamming distance) – $0 cost, computed from raw image
- Receipt ID matching – uses GPT-extracted receipt number
- Triangulation (store + date + total) – uses GPT-extracted fields
Webhook Event Parity
The admin UI now exposes exactly the webhook events that the API dispatches to customers:- Challenge completion, challenge created, challenge archived
- Achievement earned, achievement created, achievement archived
- Reward redeemed, reward created, reward archived
- Action completed (new)
- Referral reward earned, streak milestone reached
- User joined community, user left community
Referral Widget Integration
The Refer-a-Friend widget uses the existing community referral configuration and displays:- Referral reward details (points/badges)
- Copy-to-clipboard referral link
- Branded theme colors from community theme
- Mobile-optimized layout for storefront display
Index Strategy
All new indexes usepartialFilterExpression to scope only to receipt-detection actions, keeping index size minimal and avoiding pollution of other action types’ query plans.
Contributors
@Derek Counihan18 commits • +21,482/-2,019 lines
@ZuhayrK006 commits • +1,834/-423 lines
@James Cockayne4 commits • +13,392/-414 lines
@David Chen4 commits • +49/-27 lines
@SaadK941 commit • +1,339/-87 linesRelease Stats
| Metric | Value |
|---|---|
| Total Commits | 34 |
| Lines Added | +38,178 |
| Lines Removed | -2,899 |
| Files Changed | 269 |
| Release Size | 🔴 Massive |
| Complexity | ⭐⭐⭐ Complex |
Migration Guide
For Integrations Using Webhooks
If you have webhook configurations set to fire onChallengeCompletion events, no changes required — existing configs continue working unchanged.
To use action-level webhooks:
- Create a new webhook configuration in Admin Settings
- Select
ActionCompletionfrom the event picker - (Optional) Enter specific action IDs in the entity filter field to target specific actions only
- Save and test via the admin UI test button
For Receipt-Scanning Communities
The dedup system is enabled by default on all receipt-detection actions:- Default dedup window: 90 days (configurable per action)
- Dedup history only includes submissions from after v2.286.4 deploy
- For the first 90 days after deploy, the effective window grows (see admin UI help text)
For Theme Customization
Theme editor improvements are backwards compatible:- Existing theme configurations work without changes
- New features (real-time sync, undo, better keyboard nav) are automatic
- Default community selection is optional
Upgrade Notes
- No breaking changes — safe to deploy to production
- Requires database migrations for receipt dedup indexes (automatic on deploy)
- BetterStack sources updated — observability configuration change (no action needed; managed by platform)
v2.286.4 deployed on April 14, 2026

