Skip to content

EquiTrail β€” Backlog Score & Time EstimatesΒΆ

Updated: 2026-06-05 Keep this file current. Mark items βœ… when completed. Update estimates as scope changes. Win score 1–10: 10 = highest business impact (revenue, legal, retention, growth).

Legend: βœ… done Β· πŸ”„ in progress Β· blank = To Do


πŸ†• New items β€” 2026-06-05 sessionΒΆ

# Item Est. Win
#286 Premium code generator β€” Admin tool (web/admin app) to create trackable PRO codes with: code name (e.g. "John-press"), max-usage count, expiry date. Tracked in Firestore promo_codes/{code}: {name, maxUses, usedCount, usedBy:[uid], createdBy, expiresAt, isActive}. User enters code in app β†’ verifyProAccess Cloud Function validates + activates 30-day PRO. Admin sees usage in admin portal. 2d 9
#287 Referral tiers β€” Extend referral_service.dart with full tier system: 3 friends (install+active) β†’ 1 month free; 5 friends (active accounts) β†’ 1 month free; 5 premium referrals β†’ Supporter badge + 6 months free PRO; 25 premium referrals β†’ Ambassador badge + profile frame + Discord Ambassador access + extended free PRO; 50 premium referrals β†’ Elite Ambassador + 2.5% commission; 100+ premium referrals β†’ Sponsor Partner + 10% commission. Tracked in referrals/{uid} with type: 'install'|'active'|'premium' per referred user. 3d 9
#288 Referral active/premium tracking β€” When a referred user completes their first ride β†’ mark as 'active' in referral doc. When referred user upgrades to PRO β†’ mark as 'premium'. Cloud Function triggers on ride save + subscription activate. Required for tier rewards in #287. 1d 9
#289 Ambassador dashboard β€” New screen under Settings > Ambassador (only visible when role='ambassador' or higher). Shows: total referrals, active count, premium count, commission earned (if unlocked), progress to next tier, leaderboard rank vs other ambassadors. Top 3 quarterly winners get gift card/merch (tracked in Firestore). 2d 8
#290 Stable/club/instructor dashboard β€” Separate dashboard screen for accounts with role='stable'|'club'|'instructor'. Shows: how many members installed via their referral, how many converted to PRO, revenue impact. Admin can see all such accounts in admin portal. 3d 7
βœ… #291 Website region subpages β€” 55 pages (51 regions + 4 country indexes) show real rides + OSM official routes from Firestore community_trails. Toggle map layers (routes/rides). Per-province route counts on country index pages. Shared JS module: website/js/routes-region.js. done 8
#292 Trailer-friendly parking search β€” Add POI type 'trailer_parking' to POI service. In navigation screen search bar: "Paardentrailer parkeerplaats" option shows nearby trailer parking from Overpass API (amenity=parking + horse_trailer=yes OR from curated Hive dataset). Shows on map with horse trailer icon. 2d 7
#293 Arena dressage letters + course patterns β€” Expand ArenaScreen with: dressage arena letter overlay (A, K, E, H, C, M, B, F, D, X, G, V, P, R, S, I + 20Γ—40m and 20Γ—60m layouts). User can select dressage test from a list of standard Dutch proeven (Oefenklasse B, L1, L2, etc.). App shows next movement to ride. Also support non-circle patterns: serpentine (S-bocht), diagonal, half-pass, shoulder-in. Track which movements were completed and score adherence. 5d 7
#294 Jump height tracking β€” In JumpingScreen: add field for obstacle height before session. During GPS jump detection, calculate clearance = detected jump apex height - obstacle height. Show per-jump stats: obstacle height, clearance, max height reached. Session summary: average clearance, best clearance, count by height category. Store in arena_session with jumpHeights: [{height, clearance}]. 2d 6
#295 Ride detail delete button β€” Add delete button to ride_detail_screen.dart AppBar (next to share). Show confirmation dialog. Prevent accidental tap: require 2-second hold or confirmation with ride name typed. 0.5d 7
#296 Feed click β†’ ride detail view β€” When tapping a feed post, show a slide-up sheet with: ride map trace (from trackPoints if shared, else region heatmap), stats, gait bar, horse name (no real name for privacy), photos (if shared). "GPX opvragen" button sends request to ride owner. 1d 8
#297 Feed photo thumbnails β€” Show photo thumbnails in FeedPostCard when photoUrls is non-empty. Horizontal scroll of 3 small thumbnails (80Γ—80px, rounded). Tap opens full-screen gallery. Currently FeedPost.fromFirestore already reads photoUrls β€” just needs UI in feed_post_card.dart. 0.5d 7
#298 Grey screen investigate: unlock PRO β†’ track β€” Reproduced: activating PRO (HIPPISCH code) and navigating to Track tab sometimes shows brief grey screen. Likely cause: proServiceProvider rebuild cascades through horsesProvider β†’ TrackingScreen's map reinitializes. Investigate MapController lifecycle during provider cascade. 0.5d 8
#299 Nearby riders: requires active tracking β€” Users report no nearby riders despite opt-in. Root cause: publishLocation only called during active GPS tracking session. UI hint needed: "Ruiters verschijnen alleen wanneer ze actief rijden Γ©n zichtbaar zijn". Also add a test mode for admins. 0.5d 6
#300 Friend displayName in search results β€” Investigate "letters under each other" display. Likely: displayName correct in Firestore, but ListTile title is too narrow due to wide trailing widget. Fix: add maxLines:1 + overflow:ellipsis on all friend ListTile titles. 0.5d 7
#318 Parent Safety β€” Family PRO plan πŸ”’ PREMIUM MANDATORY β€” Complete parent/child safety system with child account lock. Child account restrictions (server-enforced, not bypassable client-side): GPS tracking cannot be disabled during ride Β· safety alerts locked on Β· sign-out button hidden Β· app uninstall triggers push to parent Β· all verified via Firestore family_links.parentControlled=true flag read on every launch. Parent can grant "trust unlock" per restriction individually as child matures. Core features: β€” Complete parent/child safety system. Parents buy PRO specifically for their child's safety β€” they are the paying customer. Core features: (1) Family linking β€” parent sends invite code to child's account; child accepts (both must consent β€” GDPR compliant). Child sees "πŸ”’ Bewaakt door {naam}" indicator at all times (transparency, no secret tracking). (2) Parent safety dashboard β€” dedicated screen showing all linked children: live location (during active session only), last seen, current ride distance/duration, battery level. (3) Ride start/end push notification β€” parent gets: "Emma is begonnen met rijden 🐴" + map pin, and "Emma heeft haar rit gestopt βœ… 8.4 km in 52 min". (4) No-movement alert (#312) auto-routes to parent β€” if child stopped for >5 min without pausing β†’ parent gets SMS/push before anyone else. (5) Fall detection (#313) auto-routes to parent. (6) Geofence / safe zone β€” parent draws a zone (e.g. around stable). If child rides outside: parent alerted immediately with map link. Radius: 0.5–50 km adjustable. (7) Expected return time β€” child sets "Ik ben terug om 17:00" before ride. If not returned: parent alerted at 17:05 with GPS. (8) Family PRO plan β€” new pricing tier: 1 parent + up to 3 children under one subscription. Pricing: €15/mo Β· €130/yr Β· Store: €149.99/yr (save €50/yr vs monthly β€” "meer dan 2 maanden gratis"). Child accounts get full PRO features included. (9) GDPR compliance β€” ages 13-15 (NL GDPR Art 8): parental consent required at registration. Under 13: guardian account required. Child can end monitoring link at age 16. Consent stored in Firestore with timestamp. (10) Admin visibility β€” admin can see all family links for support/abuse prevention. Firestore schema: family_links/{linkId} {parentUid, childUid, status: 'pending'|'active', consentAt, geofences: [{lat,lng,radiusKm,name}], notifyOnStart: bool, notifyOnStop: bool, expectedReturnAt: Timestamp}. Why this converts: parents are the ones paying for horses anyway. "You let your 14-year-old ride alone in the fields β€” for €15/month you always know where she is." Emotional purchase, zero price resistance. 4d 10
#322 App themes / UI skins β€” Beyond dark/light mode: full color theme skins that change the app's accent colour, gradient backgrounds, card styles and button colours. Free themes (3): Default Green (current) Β· Ocean Blue (calm blues and teals) Β· Warm Sand (earthy warm tones). PRO themes (5+): Midnight Purple Β· Rose Gold Β· Forest Dark Β· Lavender Dream Β· Golden Hour. Seasonal themes (auto-applied, admin-toggled, see #321): Sinterklaas Red Β· Christmas Snow Β· King's Day Orange. Implementation: settingsThemeKey in Hive currently stores 'system'/'light'/'dark'. Extend to include theme skin ID. MaterialApp wraps everything with ThemeData β€” skin changes the colorScheme.primary, colorScheme.secondary, gradient colors used throughout. Theme preview thumbnails shown in Settings > Uiterlijk as small app mockup cards (like image #13). Skin stored in Hive + synced to Firestore. Live preview: tap a theme β†’ app instantly updates without restart. 2d 8
#323 In-app avatar companion β€” Cute animal avatar displayed on the home screen (top-right corner, replaces or overlays the profile photo area) and on the profile screen. Acts as a visual companion that users identify with and want to collect. Horse avatars (primary β€” all breeds, styles): 🐴 Classic brown horse (free, default) Β· 🐴 White stallion (free) Β· 🐴 Black beauty (PRO) Β· 🐴 Friesian horse (PRO β€” unlock for 50 km badge) Β· 🐴 Spotted pinto (PRO) Β· 🐴 Unicorn πŸ¦„ (PRO β€” most wanted!) Β· 🐴 Golden palomino (PRO). Cute animal companions (secondary): 🐱 Black cat (free) Β· 🐰 Pink bunny (free) Β· 🦊 Fox (PRO) Β· 🐨 Koala (PRO) Β· 🐧 Penguin (PRO) Β· 🐼 Panda (PRO) Β· 🐸 Frog (PRO) Β· πŸ¦” Hedgehog (PRO) Β· 🐢 Corgi (PRO). Badge-unlocked avatars (earn them by riding): Night Owl πŸ¦‰ (unlock via hidden_nachtuil badge) Β· Rain Dancer 🌧️ frog (unlock via hidden_regendanser badge) Β· Beach Seahorse 🌊 (unlock via strandruiter badge) Β· Forest Deer 🌲 (unlock via bosverkenner badge) Β· Arctic Penguin πŸ”οΈ (unlock via 1000 km badge) Β· Galloping champion horse (unlock via five_thousand_km badge). Avatar picker screen: 3-column grid like screenshots. Lock icon πŸ”’ on premium avatars. Pink "Nieuw" badge on new additions. Silhouette shown for unearned badge-unlock avatars (visible but greyed, shows what badge unlocks it β†’ motivation to ride). Avatar display: 80Γ—80px on home screen top-right, subtle idle animation (gentle breathing/ear flick β€” Lottie JSON, <50KB each). Tap avatar on home β†’ opens avatar picker. Storage: selected avatar ID in Hive settingsAvatarKey + Firestore users/{uid}.avatarId. Avatar definitions stored in Firestore app_config/avatars (admin can add new ones without app update). PRO gate: attempt to select locked avatar β†’ bottom sheet "Upgrade naar PRO om dit dier vrij te spelen πŸ”’" Β· OR shows which badge to earn for badge-locked avatars. Asset strategy: Use emoji-style flat vector SVG/PNG assets (licence-free, included in assets/avatars/ folder). No 3D β€” flat kawaii style like the screenshots. Start with 15 avatars, grow the collection as engagement data comes in. 3d 10
#320 Seasonal promotions β€” Black Friday, Cyber Monday, Christmas β€” Annual promotional calendar with time-limited PRO discounts. Black Friday (last Friday of November): 30% off annual PRO Single + Family PRO β€” 72-hour window. In-app banner + website homepage banner + email to free users + Discord announcement. Cyber Monday (Monday after Black Friday): 20% off monthly PRO β€” 24-hour window only. Positioned as "last chance" for those who missed Black Friday. Christmas / Sinterklaas: "Geef PRO cadeau" β€” gift subscription flow: buyer pays, receives a gift code (1 month or 1 year), gives code to recipient who redeems on first login. Runs 1–24 December. Special Christmas-themed share card and email template. Technical: promo codes generated via admin (backlog #286) Β· Stripe coupon IDs stored per promotion Β· Cloud Function validates codes at checkout Β· admin dashboard shows promo redemption stats Β· codes expire 48h after campaign end. 2d 9
#321 Seasonal themes in app β€” Time-based visual theme overlays for special occasions. Sinterklaas (1–5 Dec): horse avatar gets pepernoten bag accessory, app accent colour shifts to red/gold, achievement badges get Sinterklaas hats. Christmas (15–27 Dec): snow particles on home screen, horse avatar gets reindeer antlers, "Fijne Feestdagen" greeting card on first open. New Year (31 Dec–1 Jan): fireworks animation on achievements unlocked during these dates, confetti on home screen midnight trigger. Spring (21 Mar–21 Jun): optional β€” flower crown on horse avatar, lighter greens. Easter (date-based): Easter egg hunt mini-game β€” hidden badge unlocked by tapping a hidden Easter egg in the app 3Γ— (appears in a random spot each year). King's Day NL (27 Apr): orange accent. Implementation: Theme config stored in Firestore app_config/seasonal_themes β€” admin enables/disables each theme remotely without an app update. App polls on launch (cached 6h). All animations lightweight (Lottie JSON). Themes are cosmetic only β€” no functional changes. 3d 7
#319 Family PRO β€” abuse prevention + 4+ children scaling β€” (1) Age gate: child's registered birth year must make them ≀17 at link time β€” system silently rejects adult accounts. (2) One family per child: single parent per child β€” cannot be in two families. (3) 48h invite tokens: one-time codes, expire 48h, single-use. (4) GPS overlap soft check: Cloud Function at day 30 β€” flag if parent + child never within 10km, admin reviews. (5) Fraud admin dashboard: auto-flags plans with children spanning 3+ provinces, all created same hour, or zero rides in 60 days. (6) ToS clause: subscription terminated without refund on confirmed fraud. (7) 4+ children pricing β€” simple +€3/child, no tiers: 3 kids = €15/mo (€130/yr) Β· 4 kids = €18/mo (€155/yr) Β· 5 kids = €21/mo (€180/yr). In-app when adding 4th child: single button "Extra kind toevoegen β€” +€3/mnd". (8) 6+ children = support ticket only: must provide birth certificates / BRP uittreksel proof β€” admin activates manually. Nobody fakes 6 kids for €3/month. 2d 9
#317 Conversion triggers β€” in-app FOMO & upgrade hooks β€” Smart contextual PRO prompts shown at the highest-value moments: (1) Safety trigger β€” after any ride > 5km from nearest road without a friend β†’ bottom sheet: "Je reed alleen in een afgelegen gebied. Val-detectie & noodcontact zijn beschikbaar in PRO." (2) History trigger β€” at day 85 β†’ banner in Ride History: "Je oudste ritten verdwijnen over 5 dagen uit je overzicht. Upgrade om ze te bewaren." (3) Coaching trigger β€” after 10 rides, if gait asymmetry detected (>65% one direction) β†’ "Onze analyse toont 72% rechtshandig rijden. De PRO-houdingscoach helpt dit corrigeren." (4) Badge trigger β€” when within 5% of a milestone badge β†’ "Nog 3 km voor je 100 km badge β€” PRO-ruiters ontvangen een deelbare mijlpaal-kaart." (5) Horse limit trigger β€” when user tries to add 2nd horse β†’ "Upgrade voor onbeperkte paarden." (6) Export trigger β€” on 4th GPX export of the month β†’ "Je hebt je 3 gratis exports gebruikt β€” PRO geeft onbeperkt exporteren." All triggers: one-time per category (not spammy), dismissable, track dismiss count in Hive. 2d 10
#316 Free tier redesign β€” FOMO funnel β€” Change free limits from 5 rides to: (1) Basic tracking fully unlimited β€” every ride saves forever. (2) Ride HISTORY view limited to last 90 days (free) vs all-time (PRO). (3) Horses still limited to 1 free / unlimited PRO. (4) GPX export limited to 3 per month (free) / unlimited PRO. (5) Conversion triggers: at 90-day mark β†’ "Je hebt 3 maanden ritten β€” upgrade om je volledige geschiedenis te bewaren" Β· near a badge milestone β†’ PRO coaching upsell Β· after first remote solo ride β†’ safety alert upsell. Code changes: AppConstants.freeMaxRides removed, replaced with freeHistoryDays = 90. ridesProvider filters by date for free users instead of count. RideHistoryScreen shows a "πŸ”’ Upgrade voor oudere ritten" banner when free user scrolls past 90-day cutoff. 1d 10
#315 Data protection & bot prevention β€” GPX files and ride data must never be scrape-accessible from website. (1) All Firestore feed/rides readable ONLY by signed-in users β€” no public reads of GPS track points or GPX data. (2) Website route pages show aggregated stats + start-pin only β€” no raw trackpoint coordinates in HTML/JS. (3) GPX export via app only, requires auth. (4) GPX sharing rate limit: max 10 GPX exports per user per 24h (Cloud Function check), prevents bot/scraper accounts. (5) CloudFlare WAF rule (#259) to block non-browser User-Agents on /routes/ pages. (6) honeypot hidden link in HTML to catch scrapers. (7) robots.txt Disallow: /routes/*/data β€” allow SEO crawlers on page, block data endpoints. Goal: build the ecosystem advantage β€” all the good route data is only accessible inside the EquiTrail app/account. 1d 9
#312 Safety: no-movement auto-alert β€” During an active GPS session, if the rider's speed drops below 1 km/h for more than 5 minutes WITHOUT pressing Pause, trigger a safety check. Flow: (1) Phone vibrates + shows countdown "Alles goed? Annuleer binnen 30 sec" (2) If not cancelled β†’ send emergency contact an SMS/email with: rider name, GPS coordinates, Google Maps link, timestamp, "Geen beweging gedetecteerd". Emergency contacts are managed in app Settings > Veiligheid (name + phone + email, up to 3 contacts). Also alert when GPS goes offline (phone off/dead) for >10 min during active session. Cloud Function sends the alert so it works even if phone is locked. 2d 10
#313 Safety: fall detection β€” Detect a fall using the phone's accelerometer. Fall signature: sudden G-force spike > 3g on any axis (impact), followed by near-zero motion for > 15 seconds AND session not paused. False-positive guard: 1-minute grace period where user can dismiss ("Niet gevallen - annuleer"). If not dismissed β†’ same alert flow as #312. Display fall count per session in the stats. Adjust sensitivity via Settings > Veiligheid > Valgevoeligheid (Low/Medium/High). Note: phone must be on the rider's body (not saddle bag) for accurate fall detection. Add guidance on recommended phone placement. 2d 10
#314 Posture coach β€” asymmetric rein / turn detection β€” Analyse GPS track during a session for left/right turning bias. Algorithm: count directional changes >15Β° left vs right, calculate asymmetry score (0=balanced, 100=one-sided). V1 (GPS only): at session end, show "Rij-analyse: 68% rechts β†’ controleer je linker teugel/zit". V2 (accelerometer): if phone worn on body, detect chronic lateral tilt bias during session (rider sitting crookedly). V3 (wearable): wrist IMU from Galaxy Watch gives direct hand/wrist asymmetry β€” most accurate. PRO feature. Show per-session and trend over multiple sessions. Clinically this is a known technique (equine sports science uses similar asymmetry metrics). 3d 8
#324 Hazard confirmation β€” Waze-style "still there / gone" β€” When a rider passes within 200m of a reported hazard during an active ride, show a dismissable bottom banner: "⚠️ Gevallen boom gemeld nabij. Nog aanwezig?" with two buttons: βœ… "Ja, nog daar" (confirms, resets expiry) Β· ❌ "Weg, verwijder" (marks as resolved, removes from map). After 3 "gone" confirmations from different riders the hazard auto-deletes. After 7 days with no confirmation the hazard auto-expires. POI custom report: same mechanic for user-added POIs (watering points etc.) β€” "Nog aanwezig?" prompt when passing. Admin can force-delete from admin app. Firestore: add confirmations: [], goneVotes: int, lastConfirmedAt: Timestamp, expiresAt: Timestamp to hazards/{id}. Cloud Function: daily job removes expired hazards. 1d 8
πŸ”„ #325 Auto-name completed rides β€” Cloud Function reverse-geocodes start point β†’ generates "Rit in de Veluwe β€” 12 km". Scaffolded: functions/src/auto_name_rides.ts. App: FeedPost.displayTitle getter prefers autoTitle. Pending: deploy Cloud Function, test on rides. 0.5d left 8
πŸ”„ #326 More route data sources β€” Phase 1 βœ… Phase 2 ⏳ β€” (1) βœ… OSM bridleways β€” scripts/import_osm_bridleways.py ready; bulk pre-import per region. (2) βœ… Toerisme Vlaanderen β€” scripts/import_toerisme_vlaanderen.py ready; Flanders horse routes via WFS. (3) βœ… Staatsbosbeheer β€” scripts/import_staatsbosbeheer.py ready; NL forestry GPX. (4) ⏳ Routedatabank β€” email jrietman@wandelnet.nl pending; official NL routes via WFS (most valuable source). Expected Phase 1: +2000 routes; Phase 2: +5000 routes. Total: 10,000+ across NL/BE/DE/FR. 1d now + 1d after Routedatabank 8
#311 "Find riders" public directory β€” Opt-in page at equitrail.horse/ruiters/ showing riders who have enabled public discovery. Each rider card: nickname (no real name), province/region, horse count, total km, badges. Filter by province. "Vriendverzoek sturen" button β†’ deep links to app. App setting: "Toon mij in de online ruiters-directory" (default off). Firestore: public_riders/{uid} collection with only nickname, province, stats, badges. GDPR: explicit opt-in, deletable on demand. 2d 8
#307 Ambassador / referral dashboard website page β€” Public-facing page at equitrail.horse/ambassadors/ showing: leaderboard of top referrers (anonymised, or named with consent), how the referral program works (tiers: 5 active premium β†’ Supporter badge; 25 β†’ Ambassador; 50 β†’ Elite; 100 β†’ Sponsor Partner), rewards per tier, apply/join button. Admin panel in macOS admin app shows all ambassador stats: installs, conversions, commission earned. 2d 8
#308 "Send to app" from website route pages β€” Button on each route/province page to open the route in the EquiTrail app. Android: deep link equitrail://route?lat={lat}&lng={lng}&zoom={zoom}. iOS: universal link. When app not installed: redirects to Play Store / App Store. Backend: register deep link handler in router.dart. Requires app update AND website update. 1d 7
#309 Endurance riding tracking β€” New tracking mode alongside GPS/Arena/Jumping. Endurance-specific features: heart rate zones (manual entry or BLE sensor), pace zones, cumulative altitude, mandatory rest point marking with vet check data (pulse/respiration), FEI endurance phases (pre-ride, loops 1-4, finish). TREC and CTR (Competitive Trail Riding) variants. Reports match endurance rulebooks. 4d 9
#310 Wearable expansion roadmap β€” Beyond Galaxy Watch: investigate Garmin Connect IQ (large equestrian user base), Fitbit (rebranded as Google Pixel Watch), Pebble successors (rebranded Rebble). Each needs platform SDK. Priority: Garmin Connect IQ (most popular with equestrian athletes). Document approach in docs/watch_app.md. 1d planning 7
#305 Horse stats dashboard per horse β€” Each horse card/detail shows: total km ridden on that horse, gait distribution (walk/trot/gallop %), calorie burn, number of rides, longest ride, favorite gait. If horse is used for jumping: jump count, avg/max height, personal bests. If used for arena/indoor: circle count, best session, gait balance score. Horse page tabs: "Statistieken", "Ritten", "Springen" (if relevant), "Arena" (if relevant). 2d 8
#306 Horse selection during ride β€” Before starting a GPS/arena/jumping session, rider selects which horse they're riding from their horse list (or "geen specifiek paard"). Selection shown on tracking screen. Stored with ride so stats are attributed to correct horse. Currently selection exists but no clear UX flow at session start. 1d 8
#302 Profile photo in leaderboard & ranking β€” Profile photo URL (users/{uid}.photoUrl) is not included in leaderboard docs or ranking display. Fix: when writing to leaderboard collection, include photoUrl. In the leaderboard screen widget, show CircleAvatar with NetworkImage if URL available. Same for social feed author avatar β€” currently shows first letter only. 0.5d 8
#303 Horse breed autocomplete β€” When adding/editing a horse, breed field shows a searchable dropdown with 200+ horse breeds in NL/EN/DE/FR (Appaloosa, KWPN, Friesian, Arabian, etc.). Case-insensitive, fuzzy match. Uses a curated local JSON list (no API needed). 1d 6
#304 External route importer β€” Scraper/Cloud Function to import GPX routes from equestrian route databases (e.g. hartvanlimburg.nl/en/bridleways-limburg). Stores in community_trails collection with attribution. Runs as scheduled Cloud Function (weekly). Expands database without user effort. Legal: only import publicly licensed routes. 2d 8
#301 Admin feature flag control β€” Remote Firestore config document app_config/feature_flags controls which features are Free/PRO/Hidden per user type. Admin toggle in macOS admin app (and/or Firebase Console) to change free↔PRO assignment for any feature. Hidden features exist in code but are invisible until unlocked β€” PRO users can preview "coming soon" teasers. Real-time: app listens to config doc via Firestore stream. Schema: {features: {arena: 'pro', jumping: 'pro', nearby_riders: 'free', feed: 'free', ...}, hiddenFeatures: ['dressage_letters', 'jump_height'], proTeaserMessage: 'Binnenkort...' }. Admin macOS app gets a "Feature Flags" tab with toggles. Gives fine-grained control to monetize/reward/experiment without a new release. 2d 9

πŸ’° Revenue & PaymentsΒΆ

# Item Est. Win
πŸ”„ #83 Stripe website payments (€10/mnd, 0% commission) 2d 10
πŸ”„ #84 Google Play Billing (in_app_purchase plugin + receipt verification) 3d 9
πŸ”„ #85 App Store IAP (after Apple enrollment) 3d 9
#102 🐴 Shared Rider PRO β€” Multiple riders on one horse under one subscription. Pricing: €15/mo Β· €130/yr Β· Store: €149.99/yr (save €50/yr vs monthly). One payment by horse owner unlocks full PRO for all linked co-riders. Features: ride stats per rider (same horse, separate profiles β€” km, gait, calories per person) Β· shared horse health log (vet, farrier, notes visible to all) Β· shared ride calendar (who rides when, prevent double-booking) Β· horse training log (all sessions by all riders combined). Target: stable owners with shared lesson horses (€130/yr Γ— 10 horses = €1,300/yr from one stable), families sharing a horse, riding schools. Firestore: horse_subscriptions/{horseId} {ownerUid, linkedRiderUids:[], planType:'shared_rider_pro', validUntil, stripeSubscriptionId}. 4d 8
#17 Replace manual Firestore PRO activation with Play Billing 1d 7
#18 App Store IAP β€” same scope as #85, merge 1h 3
#87 Document full free vs PRO feature list (website + app) 4h 5
#1 Payment options page (overlaps #83–85, low added value) 4h 4

πŸ“± iOS & AppleΒΆ

# Item Est. Win
#35 Enroll in Apple Developer Program (€99/yr β€” admin task) 2h 10
#36 Install EquiTrail on iPhone SE via flutter run 1h 6
#41 TestFlight: first external iOS build after enrollment 4h 9
#32 Submit EquiTrail to App Store 1d 9
#42 iOS APNs push notifications (friend requests, ride reactions) 2d 7
#23 Apple DeviceCheck (iOS equivalent of Play Integrity) 1d 5
#20 Apple Watch companion app (watchOS target in Xcode) 2w 6

⌚ Galaxy Watch (POST-LAUNCH β€” deprioritised)ΒΆ

# Item Est. Win
βœ… #188 CRITICAL: Galaxy Watch crash loop β€” 3 bugs fixed, v1050 wear:internal done 10
#33 Confirm Galaxy Watch update to v1050 + physical watch test 30m 4
#21 Galaxy Watch: heart rate display in PRO mode 2d 4

πŸ§ͺ Launch Test Plan & AutomationΒΆ

# Item Est. Win
πŸ”„ #213 Launch test plan β€” docs/test_plan.md (functional, UX, regression, platform) done 9
πŸ”„ #214 Automated integration test suite β€” 18 tests, all screens, bug detection, Azure DevOps auto-issues done 9

🐴 Core App Features¢

# Item Est. Win
#22 Push notifications β€” FCM (friend requests, badges, club activity) 3d 9
#94 Full ride history on website (logged in, Firestore-backed) 3d 8
βœ… #93 Hidden badges: isHidden field, ??? render, 5 badges (Nachtuil/Regen/Carrousel/Hollander/Veteraan) done 8
βœ… #40 Friend request in-app notification β€” Firestore notifications collection + notificationsStream + tab badge done 7
βœ… #89 GPX request from feed β€” requestGpx(), 3-dot menu "Vraag GPX-bestand", owner in-app notification done 6
πŸ”„ #106 Automated test plan β€” integration_test/app_test.dart + scripts/run_tests.sh + docs/bugtracker.md 2d 8
#90 Clubs: group chat with emoticons (no media) 5d 6
#30 Improve jump detection accuracy with accelerometer 3d 5

# Item Est. Win
#101 Routing server fallback (OSRM secondary when GH down) 1d 7
#25 Belgium + Germany full routing graph merge 2d 6
#26 France OSM merge 1d 5

🌐 Social & Community¢

# Item Est. Win
βœ… #104 Block/report: blockUser/unblockUser, feed filter, report sheet, auto-hide @3, blocked users settings screen done 9
#27 Custom friend groups with names 2d 5
#28 Group feed filtered to club/friends 1d 5
βœ… #91 Photo moderation: Discord #photo-moderation + webhook + /delete-post + /gdpr-request done 6

πŸ€– Discord & BotΒΆ

# Item Est. Win
#88 Support Bot: auto-create tickets from #bug-reports + #feature-requests 1d 7
#69 Sync app badges/roles to Discord via OAuth 3d 6
#68 Discord: route lookup + GPX delivery (mostly done via RouteHelper) 4h 5

πŸ“Έ Media & IPΒΆ

# Item Est. Win
βœ… #103 Health & medical disclaimer β€” ToS all 4 langs done 9
βœ… #100 Social media watermark + branded card on photo share (PhotoService) done 7
βœ… #99 EXIF metadata on ride photos (EquiTrail software, artist, datetime, GPS comment) done 5
βœ… #91 Photo moderation: Discord #photo-moderation channel + webhook + /delete-post + /gdpr-request done 6
βœ… #92 IP protection β€” copyright headers + Terms of Service done 8

# Item Est. Win
βœ… #105 Account & data deletion request page (equitrail.horse/delete-account) done 10
βœ… #94 equitrail.horse/history β€” Firebase Auth, Firestore rides, Leaflet maps, GPX export done 8
βœ… #104 Block/report: blockUser/unblockUser, feed filter, report sheet, auto-hide @3, blocked users settings screen done 9
βœ… #103 Health & medical disclaimer β€” ToS all 4 languages done 9
βœ… #92 IP protection β€” copyright headers + Terms of Service done 8

πŸ”Œ IntegrationsΒΆ

# Item Est. Win
#137 Fix Firestore Admin SDK 403 β€” firestore.googleapis.com SERVICE_DISABLED despite being enabled in console. Code ready in get_firestore_stats(). Dashboard shows N/A until fixed. 1h 6

πŸ›‘οΈ Ops & AdminΒΆ

# Item Est. Win
βœ… #96 Disaster recovery plan + quarterly DR test done 9
βœ… #97 Comprehensive backup plan (code + secrets) done 9
βœ… #98 Client media backup β€” GCS bucket + lifecycle + setup script done 8
βœ… #95 Admin dashboard CLI + web done 7
#24 Certificate pinning on API calls 1d 5

🎧 Support System¢

# Item Est. Win
#49 AI bot on equitrail.horse (Claude Haiku, NL/EN/FR/DE) 2d 8
#50 AI bot: knowledge base from docs/ (RAG pipeline) 2d 7
#51 AI bot: escalate to ticket with conversation context 1d 7
#52 Support portal: setup support.equitrail.horse 1d 6
#53 Support portal: knowledge base articles (NL/EN/FR/DE) 2d 6
#54 Support portal: ticket system + AI pre-screening 3d 7
#55 Support portal: admin ticket queue + reply UI 2d 6

πŸ” Admin PanelΒΆ

# Item Est. Win
βœ… #215 Admin panel β€” users, PRO, badges, moderation, GDPR, routes map done 8

Design: separate subdomain (admin.equitrail.horse) or Oracle Docker behind Tailscale (not on main site β€” less public target). Firebase Auth gate (admin-only). Features: user search/edit, grant PRO, approve badges, photo moderation queue, GDPR deletion requests, install stats.


🌍 Website Intelligence¢

# Item Est. Win
βœ… #107 Geo-language detection β€” ipapi.co, cached 24h, manual override, all pages via nav.js done 7

πŸͺ Store Assets & MarketingΒΆ

# Item Est. Win
#56 Play Store: screenshots all sizes NL/EN/FR/DE 2d 8
#57 Play Store: descriptions + ASO keywords NL/EN/FR/DE 1d 8
#58 Play Store: feature graphic 1024Γ—500 + icon review 4h 6
#59 App Store: screenshots NL/EN/FR/DE (6.7", 5.5", iPad) 2d 8
#60 App Store: title, subtitle, keywords, categories 1d 7
#61 App Preview video (30 sec) 3d 7
βœ… #29 equitrail.horse/riders β€” rider discovery landing page with real Veluwe Leaflet map done 6
βœ… #87 Free vs PRO comparison table + updated feature cards + pricing fixes in index.html done 5
#70 Create Facebook, X, Instagram, TikTok profiles 4h 6

πŸš€ AI Social Media AutomationΒΆ

# Item Est. Win
#71 Detect new public rides with photos β†’ content queue 2d 6
#72 Generate Reels/Shorts from GPS track animation 5d 7
#73 Generate captions + hashtags via Claude API 1d 7
#74 Auto-post to Facebook, X, Instagram, TikTok 2d 6

πŸ“¬ Newsletter & Email MarketingΒΆ

Recommended service: Brevo (brevo.com) β€” EU-based (FR), GDPR native, free up to 300 emails/day. At scale (>5k subs): migrate to self-hosted Listmonk on Oracle server. Sending infrastructure: Brevo SMTP or Amazon SES (€0.10/1000 emails). All opt-ins must be explicit double opt-in per GDPR Art. 7. Never purchased lists.

# Item Est. Win
#241 Newsletter opt-in β€” app Settings + website footer; store consent + timestamp in Firestore users.newsletterOptIn, newsletterOptInAt, newsletterRegion, newsletterPrefs S (1d) 8
#242 Brevo account setup β€” create account at brevo.com, add DPA, connect equitrail.horse sending domain (SPF/DKIM), verify sender nossiej@... or newsletter@equitrail.horse XS (2h) 8
#243 Newsletter preferences centre β€” page at equitrail.horse/newsletter: manage frequency (weekly/bi-weekly), topics (tips/ritten/regionaal), one-click unsubscribe; update Firestore + Brevo contact S (1d) 7
#244 Newsletter generator script β€” scripts/generate_newsletter.py: pulls top community_trails by region, app changelog, riding tips from KB, regional rider stats; generates responsive HTML using Brevo template API; sends via Brevo API M (2–3d) 9
#245 Weekly newsletter content β€” auto-generated sections: πŸ—ΊοΈ Top gedeelde routes in jouw regio Β· πŸ‡ Toprijders leaderboard Β· πŸ’‘ Rijderstip van de week Β· πŸ†• Nieuw in EquiTrail Β· ⭐ Review-verzoek (Play Store / App Store) M (2d content + automation) 9
#246 Review request in newsletter footer β€” every newsletter includes: "Vind je EquiTrail handig? Laat een recensie achter op [Play Store / App Store]" with correct store link per platform (stored in user profile); GDPR note XS (2h) 9
#247 GDPR compliance β€” unsubscribe link in every email (one-click), EU data residency confirmed, consent audit log, DPA with Brevo, privacy policy update S (0.5d) 10
#248 Transactional integration β€” after support ticket resolved: 2 days later send follow-up with review request; after 3 months PRO: retention email with new features; all conditional on newsletterOptIn M (2d) 7
#249 Region segmentation β€” derive region from Firestore user location or GPS cluster; tag contacts in Brevo with region (Noord-Holland, Gelderland etc.); send region-specific ride highlights M (2–3d) 8
#250 Listmonk migration (future) β€” self-host on Oracle when > 5k subs; import from Brevo; own domain tracking L (1w) 6

Newsletter content sections (#244/#245 detail)ΒΆ

Each newsletter contains: - πŸ‡ Ruiter van de week β€” spotlight on a rider who opts in via in-app prompt or website form. Short bio, best route, horse name. Requires: opt-in form in app/website, admin approval flow. Tag: newsletterSpotlight: true in Firestore. - πŸ—ΊοΈ Route van de maand β€” top community trail by likes/shares in the past month, per region. Auto-pulled from community_trails orderBy likes desc. GPX download link included. - πŸ’‘ Rijderstip van de week β€” rotating from KB articles (gps-tracking.html, horses.html etc.), written in friendly NL tone. - πŸ“Š Jouw statistieken deze maand β€” personalised section: km gereden, best rit, badge unlocked. Requires: merge tag support in Brevo. - πŸ†• Nieuw in de app β€” curated from CHANGELOG.md, simplified for non-technical readers. - ⭐ Laat een recensie achter β€” "Help ons groeien: {Play Store link / App Store link}" β€” platform-aware based on platform field in user doc. - πŸ“© Wil jij featured worden? β€” CTA: "Ben jij onze volgende Ruiter van de Week? Mail je verhaal naar spotlight@equitrail.horse"

Implementation order:ΒΆ

  1. #247 GDPR policy update (prerequisite for everything)
  2. #242 Brevo setup (2h)
  3. #241 Opt-in in app + website
  4. #243 Preferences centre
  5. #244 + #245 Generator + content (including spotlight, route of month)
  6. #246 Review request footer
  7. #248 + #249 Advanced automation

πŸ—ƒοΈ Misc / Early backlog (low priority, overlap with above)ΒΆ

# Item Est. Win
#2 Add bonus ideas (vague β€” merge into relevant items) β€” 2
#3 Referral bonus (ET-code system exists, extend only) 1d 5
#4 Promo / act-now pages on website 1d 4
#5 Campaigns system 3d 4

πŸ† Top priorities (not yet started, sorted by win)ΒΆ

Rank # Why
1 #35 Apple Developer enrollment Unlocks #32, #41, #42, #85 β€” entire iOS track blocked on this
2 #33 Test Galaxy Watch install 2 hours, potentially marks watch as live in production
3 #98 Firebase Storage β†’ GCS backup 4 hours, protects all user photos permanently
4 #56/#57 Play Store screenshots + ASO Direct install growth, no proper store presence yet
5 #88 Discord support bot 1 day, saves hours of manual support per week

πŸ—οΈ Infrastructure Scaling β€” Growth Readiness PlanΒΆ

Principle: No vendor lock-in at the data layer. Firebase Auth + Firestore are fine for launch, but the rides/tracks data must remain portable. Build with abstraction layers from day 1. Current stack review date: 2026-06-04. Re-evaluate at each phase threshold.

Current stack (Phase 1 β€” 0–2,000 users)ΒΆ

Component Service Cost Vendor risk
Database Firebase Firestore (europe-west4) Free tier Medium β€” mitigatable
Auth Firebase Auth Free tier Low β€” OAuth2 standard
File storage Firebase Storage Free tier Medium β€” use signed URLs
App hosting Plesk (equitrail.horse) ~€20/mo Low β€” easy to move
Backend services Oracle Cloud ARM (free tier) €0 Low β€” Docker, portable
Email Office 365 shared mailbox existing Low β€” SMTP replaceable
CDN None yet €0 N/A

Phase thresholds and actionsΒΆ

# Item Trigger Est. Win
#251 Phase 2 prep (2k–10k users) β€” Enable Firebase Blaze billing, set spend alerts at €50/€100/€200, monitor Firestore reads/writes/Storage daily. Add Cloudflare free CDN in front of equitrail.horse. Expected Firebase cost: €20–80/month 1,500 active users S (1d) 7
#252 Firestore cost optimisation β€” GPS tracks stored as compressed JSON blobs (already done). Add Firestore TTL on active_riders (2h), rider_discovery (24h). Batch writes for ride saves (reduce write count 60–80%). Cache leaderboard in Firestore (not real-time). 5k rides/month M (2d) 9
#253 Phase 3: PostgreSQL for rides (10k–50k users) β€” Rides data (GPS tracks, stats) migrated from Firestore to managed PostgreSQL (Supabase europe-west or Neon.tech serverless). Firestore remains for social/feed/settings (fits its NoSQL strength). Migration path: dual-write β†’ backfill β†’ cutover. Ride data is structured = major cost saving. Estimate: Firestore rides cost €300/mo at 50k users vs €30 PostgreSQL 10,000 registered users OR Firestore bill > €100/mo XL (2w) 10
#254 Firebase Storage β†’ Cloudflare R2 β€” Photo storage migrated to Cloudflare R2 (zero egress fees, S3-compatible API). Firebase Storage charges egress; R2 does not. Simple swap: update upload/download URLs. No vendor lock β€” standard S3 API Firebase Storage bill > €30/mo M (3d) 8
#255 Redis/Valkey caching layer β€” Add Redis (Valkey open source) on Oracle server for: leaderboard cache (1hr TTL), nearby riders cache (30s), feed cache (5min). Reduces Firestore reads by ~70% for social features. Free on Oracle (4 OCPUs, 24GB RAM has headroom) 5,000 daily active users M (3d) 9
#256 Oracle β†’ Hetzner migration (if Oracle free tier disappears) β€” All Oracle services containerised (Docker Compose). Migration = copy docker-compose.yml + volumes to Hetzner CX21 (€5/mo, Frankfurt = EU). Services: Discord bot, support daemon, routing server (OSRM). Preparation: document all volumes, keep compose file up to date If Oracle reclaims free tier S (1d prep) 10
#257 Phase 4: Full backend extraction (50k+ users) β€” Replace Firebase as primary backend with: FastAPI (Python) on Cloud Run (europe-west4, scale to zero), Supabase for PostgreSQL + Auth (can keep Firebase Auth as identity provider, just switch DB). Firestore stays for real-time feeds only. Eliminates vendor lock risk entirely 50,000 registered users OR Google announces Firebase pricing change XL (4–6w) 8
#258 Anti-lock preparation (ongoing) β€” Abstract all Firebase calls behind service classes (already partially done). Document data export procedures. Maintain Firestore export to GCS weekly (backlog #backup). Never use Firebase-specific features that have no open standard equivalent Now β€” ongoing S (1d) 10
#259 CDN + DDoS protection β€” Cloudflare (free plan) in front of equitrail.horse + support.equitrail.horse. Protects Plesk, hides origin IP, free SSL, caching static assets. 5-minute setup Now XS (2h) 8
#260 Load testing baseline β€” locust script simulating 1k concurrent users: ride save, feed load, leaderboard, nearby riders. Run before each major release. Document baseline metrics Before Play Store public launch M (2d) 7

Vendor lock risk matrixΒΆ

Vendor Lock risk Mitigation Escape hatch
Firebase/Google Medium Abstract behind service classes, export weekly Supabase, Neon, Appwrite
Oracle free tier Low-Medium Docker Compose, portable Hetzner (€5/mo), DigitalOcean
Play Store None (Android monopoly) β€” Sideload APK as backup
App Store None (iOS monopoly) β€” β€”
Office 365 Low Standard SMTP Brevo, SES, Postfix
Plesk hosting Low Static files, easy copy Cloudflare Pages, Hetzner

πŸ“ˆ Growth Campaign Plan β€” 12-Month RoadmapΒΆ

Target market: Dutch recreational horse riders (primary), Belgium + Germany (month 6+). Equestrian sport in NL: ~400,000 registered riders, ~1.5M horse enthusiasts. Word-of-mouth at the stable is the #1 growth channel β€” design for it.

Realistic projectionsΒΆ

Milestone Timeline Trigger
100 users Month 1 Beta testers + referrals
500 users Month 2–3 App Store live + first influencer
2,000 users Month 4–6 Paid ads + manege partnerships
5,000 users Month 6–9 Viral route sharing, newsletter
10,000 users Month 10–12 Expansion BE/DE, press
25,000 users Year 2 Scale paid + community flywheel

Backlog itemsΒΆ

# Item Timeline Budget Est. Win
#261 App Store & Play Store ASO β€” Professional screenshots (phone + tablet), keyword-optimised NL/EN/DE/FR descriptions, short promo video (foreground GPS permission), A/B test icons. ASO = highest ROI growth lever. Month 1 €0 M (3d) 10
#262 Review request flow β€” In-app prompt after 3rd completed ride (not annoying): "Vind je EquiTrail fijn? Help ons groeien 🐴" β†’ direct to Play Store / App Store. Also in newsletter footer and after resolved support ticket (2 days later). Month 1 €0 S (1d) 10
#263 Referral campaign push β€” Active marketing of existing ET-code system. "Nodig 3 vrienden uit, allen 1 maand PRO gratis". WhatsApp template, Instagram story template, stable poster (A4 PDF) for download at equitrail.horse/deel. Month 1 €0–100 design S (1d) 9
#264 Instagram account (@equitrail.horse) β€” 3x/week posting: GPS track animations (auto-generated from community_trails), rider spotlights, tips, "Rit van de week". Dutch primary, English secondary. Content calendar 4 weeks ahead. Target: 1k followers month 3. Month 1 ongoing €0 M (content ongoing) 8
#265 Micro-influencer outreach (NL) β€” Identify 10 Dutch equestrian Instagram accounts 5k–50k followers (lifestyle focus, not only competition). Offer: 6 months PRO free + branded content brief. No cash initially. Follow-up with paid deal if conversion good. Target accounts: managebloggers, jonge ruiters, KWPN fokkers, dressuur-lifestylers Month 2 €0 (PRO codes) M (2d outreach + follow-up) 9
#266 Manege/rijschool partnership programme β€” Email 50 managements in NL: offer "Manege PRO deal" β€” school gets 5 free PRO accounts, students get 30-day free trial on sign-up with stable code. Tracking: stableCode field in Firestore. Partner logo on website "Aangesloten managements" Month 2–3 €0 M (2d) 8
#267 Google UAC (Universal App Campaigns) β€” Android-only first. €200/month initial budget, target: equestrian keywords + competitor terms. Target CPI (cost per install) < €1.50. Measure retention D7/D30 to optimise. Pause if CPI > €3 without improving. Month 3 €200/mo S (setup 1d) 8
#268 Facebook/Instagram Ads β€” Target: NL women 20–45, interests: paarden, manege, KWPN, dressuur, springen. Lookalike from existing users. €150/month initial. Creative: GPS track animation video, "Houd jij je ritten bij?" Month 3 €150/mo S (setup 1d) 7
#269 TikTok / Reels content β€” Short GPS track animations (30s), "dag in het leven van een ruiter" format. Auto-generate from community_trails data (backlog #72). If Instagram Reels performing: repurpose to TikTok. Target: younger riders 16–28 Month 4 €0 M (2d setup) 7
#270 Press & media β€” Reach out to: Hoefslag.nl, Paardenkrant, Ruitersport.com, Horses.nl. Press kit: app demo video, stats, unique angle ("GPS rit app speciaal voor ruiters, gemaakt door een ruiter"). Target: 1 feature article month 4 Month 4 €0 M (2d) 9
#271 Community challenges β€” Monthly challenge: "Meeste km in april" (leaderboard), "Langste rit van de week", seasonal (zomer/winter). Share results to feed + social. Creates recurring engagement and shareability Month 3 ongoing €0 M (2d) 8
#272 Belgium expansion β€” French/Dutch-speaking Belgium. Translate Store listing to FR (done) + NL. Reach out to Belgian equestrian federation. Target Belgian equestrian Instagram accounts. Budget: same as NL phase, 3 months later Month 6 €100/mo extra ads S (1d) 7
#273 Germany expansion β€” DE translation done. Target: DOKR (Deutsche Olympiade-Komitee fΓΌr Reiterei) community, German equestrian Instagram. German App Store listing. Month 7 €200/mo extra ads S (1d) 7
#274 Partnerships with horse event organisers β€” Sponsor presence at KWPN Keuring, Dutch Championships, local concours. EquiTrail booth/banner + QR code to download. Leaflets at check-in. Budget: €200–500 per event Month 5+ €300/event S (1d prep) 8
#275 Ambassador programme β€” 5–10 active power-users get "EquiTrail Ambassador" role (Discord + app badge). Perks: lifetime PRO, exclusive features preview, monthly video call. Obligation: share 2x/month, gather stable feedback Month 3 €0 S (1d) 8

Budget planΒΆ

Period Monthly budget Allocation
Month 1–2 €0–100 Design assets only
Month 3–4 €400/mo UAC €200 + FB/IG €150 + tools €50
Month 5–6 €700/mo UAC €300 + FB/IG €250 + events €150
Month 7–12 €1,200/mo Scale winning channels + BE/DE ads
Year 2 €2,500/mo Full funnel if revenue supports (target: CAC < LTV/3)

Key metrics to track (monthly)ΒΆ

  • Downloads (organic vs paid)
  • D1 / D7 / D30 retention
  • Rides created per user per week
  • Referrals activated
  • Review score (Play Store / App Store)
  • CAC (cost per acquired user) by channel
  • MRR growth

🚨 Growth & Infrastructure Threshold Alerting¢

Goal: Be ahead of scaling issues, not reactive. Get alerted BEFORE hitting limits, not when the app is already slow or expensive. Every alert should fire with enough lead time (2–4 weeks) to act without panic.

# Item Trigger Est. Win
#276 Firebase spend alerting β€” GCP billing alerts: €20/mo (info), €50/mo (warning), €100/mo (urgent β†’ scale review meeting). Firebase quota alerts: Firestore reads >80% daily limit, Storage >80% free tier. Alert via: Discord #ops-alerts + email nossiej@gmail.com Now XS (2h) 10
#277 User growth threshold dashboard β€” Automated weekly Discord message (Monday 09:00) via cron on Oracle: "πŸ“Š EquiTrail week report: {users_total} users Β· {new_this_week} new Β· {rides_this_week} rides Β· {dau} DAU Β· Firebase cost: €{cost}". Pulls from Firestore Admin SDK + GCP billing API Month 1 S (1d) 9
#278 Firestore performance monitoring β€” Track read/write counts daily. Alert when: daily reads >30k (Spark limit: 50k), daily writes >15k (limit: 20k), Storage >3GB (limit: 5GB). Cron script checks Firestore usage stats via GCP API β†’ posts to Discord if thresholds hit Now S (1d) 9
#279 Scaling trigger checklist β€” Auto-generated checklist posted to Discord when threshold reached: "⚠️ Firestore approaching free tier limit. Actions needed: 1) Enable Blaze billing 2) Add spend cap 3) Review top write operations 4) Enable TTL on active_riders". Prevents scrambling at the last minute. Automatic S (0.5d) 9
#280 Oracle server health alerts β€” Daily check: CPU >80% avg, RAM >85%, disk >80%, bot uptime, support daemon uptime, routing server uptime. Alert via Discord #ops-alerts. Script: extend existing scripts/dashboard.py with thresholds Now S (0.5d) 8
#281 App crash rate alerting β€” Firebase Crashlytics (add to app): alert if crash-free session rate drops below 99.5%. Daily digest of top crashes. Integrates with existing Discord bot β†’ #bug-reports Month 1 S (1d) 9
#282 Monthly scaling review (calendar) β€” Recurring calendar item: 1st Monday of every month, 30 minutes. Checklist: review Firebase costs vs budget, user growth vs projections, infrastructure load, upcoming thresholds. Documented decision: scale up / hold / optimise. Now XS (30min setup) 10
#283 GCP budget anomaly detection β€” Enable GCP "Budget alerts with forecast" β€” warns if spending trajectory will exceed budget before end of month. Also: set hard cap on Firebase Functions (€0 until intentionally enabled) to prevent runaway costs Now XS (1h GCP console) 9
#284 Play Store / App Store review monitoring β€” Daily check of new reviews (Play Store API + App Store RSS). Negative review (1–2 stars) β†’ Discord alert within 1h β†’ admin can respond fast. Pattern: 3+ similar negative reviews in a week β†’ create auto-backlog bug item Month 1 S (1d) 8
#285 Infrastructure scaling playbook β€” docs/scaling_playbook.md: step-by-step for each threshold. "When Firebase reads hit 40k/day: [step 1] add Firestore TTL on active_riders [step 2] enable caching [step 3] ...". Written once, followed under pressure. Month 1 S (1d) 8

Alert routingΒΆ

Alert type Channel Response time
Firebase cost > €50 Discord #ops-alerts + email 24h
Firebase quota > 80% Discord #ops-alerts 48h
App crash rate < 99.5% Discord #bug-reports 4h
Oracle disk > 80% Discord #ops-alerts 24h
Oracle service down Discord #ops-alerts 1h
Negative review spike Discord #ops-alerts 1h
User growth milestone (100/500/1k/5k/10k) Discord #general πŸŽ‰ Celebrate!