[{"data":1,"prerenderedAt":427},["ShallowReactive",2],{"/projects/bet-monks-world-cup-predictions":3},{"id":4,"title":5,"body":6,"description":387,"extension":409,"featured":410,"meta":411,"navigation":412,"path":413,"seo":414,"sortOrder":415,"stem":416,"tagline":417,"tags":418,"__hash__":426},"projects/projects/bet-monks-world-cup-predictions.md","Bet.Monks World Cup Predictions",{"type":7,"value":8,"toc":386},"minimark",[9,60,64,68,73,77,80,88,91,95,140,142,146,149,151,155,158,175,178,180,184,189,197,201,204,224,228,242,246,260,264,275,277,281,284,287,301,304,306,310,318,322,336,340,351,353,357,377,379,383],[10,11,26,27,26,37],"div",{"className":12},[13,14,15,16,17,18,19,20,21,22,23,24,25],"mb-8","flex","items-center","gap-4","rounded-xl","border","border-slate-200","bg-white/60","px-4","py-3","backdrop-blur","dark:border-slate-800","dark:bg-slate-950/50","\n  ",[28,29],"img",{"src":30,"alt":31,"className":32},"/images/logos/mm.svg","MM",[33,34,35,36],"bet-monks-mm-logo","h-6","w-auto","object-contain",[10,38,42,43,42,52,26],{"className":39},[14,40,41],"flex-col","leading-tight","\n    ",[44,45,51],"span",{"className":46},[47,48,49,50],"text-xs","font-medium","text-slate-500","dark:text-slate-400","\n      Client\n    ",[44,53,59],{"className":54},[55,56,57,58],"text-sm","font-semibold","text-slate-900","dark:text-slate-100","\n      Media.Monks\n    ",[61,62],"stack-chips",{":items":63},"[\"Node.js\", \"NestJS\", \"TypeScript\", \"MongoDB\", \"Vue.js\", \"Quasar Framework\", \"OAuth 2.0 (Google)\", \"AWS S3\", \"Simple Queue Service (SQS)\", \"Swagger\"]",[65,66],"media-carousel",{":items":67},"[{\"type\": \"image\", \"src\": \"/images/projects/betmonks/loginpage.png\", \"caption\": \"Google OAuth login screen restricting access to authorized Media.Monks employee accounts.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/fmybets.png\", \"caption\": \"My Bets dashboard showing upcoming matches, submitted predictions, points, and personal ranking metrics.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/smybets.png\", \"caption\": \"Detailed My Bets view with match-by-match prediction status, results, and scoring feedback.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/results.png\", \"caption\": \"Tournament results page displaying match outcomes and stage progression across the competition.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/ostandings.png\", \"caption\": \"Overall standings leaderboard with participant rankings, accumulated points, and tie-break ordering.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/rules.png\", \"caption\": \"Rules page explaining the scoring system used to evaluate predictions fairly and consistently.\"}, {\"type\": \"image\", \"src\": \"/images/projects/betmonks/srules.png\", \"caption\": \"Scoring rules detail view highlighting priority-based point assignment for each prediction outcome.\"}]",[69,70,72],"h2",{"id":71},"overview","Overview",[74,75,76],"p",{},"Bet.Monks was an internal prediction platform built for Media.Monks during the FIFA Women's World Cup 2023. Employees could submit score predictions before kickoff, earn points based on scoring rules, and compete in a live leaderboard throughout the tournament.",[74,78,79],{},"I owned the application layer end to end, building both the backend and frontend that powered authentication, prediction flows, scoring, rankings, and tournament views.",[81,82,85],"callout",{"title":83,"type":84},"Project Scope","info",[74,86,87],{},"This case study focuses on the application development work I delivered: backend APIs, frontend experience, data modeling, scoring logic, ranking updates, and asynchronous result processing.",[89,90],"hr",{},[69,92,94],{"id":93},"my-contribution","My Contribution",[96,97,99],"contribution",{"role":98},"Full-Stack Engineer",[100,101,102,115,125,128,131,134,137],"ul",{},[103,104,105,106,110,111,114],"li",{},"Designed and implemented the backend API in ",[107,108,109],"code",{},"NestJS"," (",[107,112,113],{},"TypeScript",")",[103,116,117,118,121,122],{},"Built the frontend application in ",[107,119,120],{},"Vue.js"," + ",[107,123,124],{},"Quasar",[103,126,127],{},"Implemented Google OAuth 2.0 login restricted to authorized company accounts",[103,129,130],{},"Designed MongoDB models for matches, predictions, users, standings, and tournament data",[103,132,133],{},"Built the scoring and ranking engine with deterministic rule evaluation",[103,135,136],{},"Implemented asynchronous processing for match result updates and leaderboard recalculation",[103,138,139],{},"Documented backend endpoints with Swagger for maintainability and team collaboration",[89,141],{},[69,143,145],{"id":144},"problem","Problem",[74,147,148],{},"Media.Monks needed an internal-only platform that could keep employees engaged throughout the tournament while handling a core product challenge: predictions had to be easy to submit before kickoff, but scoring and ranking also needed to remain consistent, fair, and automatically updated as official match results came in.",[89,150],{},[69,152,154],{"id":153},"solution","Solution",[74,156,157],{},"I built Bet.Monks as a full-stack web application with a modular backend and a responsive frontend experience tailored to tournament participation. The system supported the full prediction lifecycle:",[100,159,160,163,166,169,172],{},[103,161,162],{},"Secure employee authentication via Google OAuth",[103,164,165],{},"Pre-kickoff score submissions",[103,167,168],{},"Match result display and point breakdowns",[103,170,171],{},"Automatic ranking recalculation after final results",[103,173,174],{},"Tournament progress tracking across group and knockout stages",[74,176,177],{},"To keep the user experience responsive, match finalization and scoring recalculation were processed asynchronously instead of blocking user-facing requests.",[89,179],{},[69,181,183],{"id":182},"application-features","Application Features",[185,186,188],"h3",{"id":187},"login-page","Login Page",[100,190,191,194],{},[103,192,193],{},"Google OAuth 2.0 authentication for employee access",[103,195,196],{},"Internal-only access control using authorized company accounts",[185,198,200],{"id":199},"my-bets-page","My Bets Page",[74,202,203],{},"Primary interaction surface for the tournament.",[100,205,206,209,212,215,218,221],{},[103,207,208],{},"View upcoming matches",[103,210,211],{},"Submit score predictions before kickoff",[103,213,214],{},"See completed match results and points earned",[103,216,217],{},"Track total points, ranking position, and prediction count",[103,219,220],{},"View the most predicted score for each match",[103,222,223],{},"Dynamic UI updates based on match status and user activity",[185,225,227],{"id":226},"results-page","Results Page",[100,229,230,233,236,239],{},[103,231,232],{},"Group stage tables",[103,234,235],{},"Knockout bracket rounds and final standings",[103,237,238],{},"Match metadata (date, time, location, score)",[103,240,241],{},"Dynamic handling of different tournament stages",[185,243,245],{"id":244},"overall-standings-page","Overall Standings Page",[100,247,248,251,254,257],{},[103,249,250],{},"Live participant leaderboard",[103,252,253],{},"Total accumulated points and ranking positions",[103,255,256],{},"Tie-break ordering and comparative standings",[103,258,259],{},"Automatic recalculation after result processing",[185,261,263],{"id":262},"rules-page","Rules Page",[100,265,266,269,272],{},[103,267,268],{},"Clear scoring rules for participants",[103,270,271],{},"Priority-based point assignment to ensure each prediction is scored once per match",[103,273,274],{},"Consistent rule enforcement across all users",[89,276],{},[69,278,280],{"id":279},"scoring-ranking-system","Scoring & Ranking System",[74,282,283],{},"The scoring engine was the core application component and a key part of the backend design.",[74,285,286],{},"When a match result became final, the system:",[100,288,289,292,295,298],{},[103,290,291],{},"Evaluated all related predictions",[103,293,294],{},"Applied scoring rules using a single-priority outcome per prediction",[103,296,297],{},"Recalculated user totals",[103,299,300],{},"Updated leaderboard positions and tie-break ordering",[74,302,303],{},"This logic was implemented to be deterministic and repeatable, which was essential for fairness in a competitive internal platform.",[89,305],{},[69,307,309],{"id":308},"technical-highlights","Technical Highlights",[311,312,315],"decision",{"title":313,"tradeoff":314},"Asynchronous result processing for scoring updates","More backend coordination → faster user-facing interactions",[74,316,317],{},"Scoring and leaderboard recalculation were triggered asynchronously after match results were finalized. This kept the application responsive while processing many predictions and ranking updates in the background.",[185,319,321],{"id":320},"backend-nestjs","Backend (NestJS)",[100,323,324,327,330,333],{},[103,325,326],{},"Modular API design for authentication, predictions, matches, results, and standings",[103,328,329],{},"Swagger documentation for endpoint visibility and faster maintenance",[103,331,332],{},"MongoDB data modeling aligned with tournament entities and prediction workflows",[103,334,335],{},"Queue-based asynchronous processing for result finalization and scoring updates",[185,337,339],{"id":338},"frontend-vuejs-quasar","Frontend (Vue.js + Quasar)",[100,341,342,345,348],{},[103,343,344],{},"Responsive UI for desktop and mobile participation during the tournament",[103,346,347],{},"Tournament-focused screens for bets, results, standings, and rules",[103,349,350],{},"Dynamic state-driven updates based on match lifecycle and user predictions",[89,352],{},[69,354,356],{"id":355},"what-this-project-demonstrates","What This Project Demonstrates",[100,358,359,362,365,368,371,374],{},[103,360,361],{},"Full-stack ownership of an application used during a live event timeline",[103,363,364],{},"Implementation of competitive scoring and ranking logic",[103,366,367],{},"Secure internal authentication with OAuth 2.0",[103,369,370],{},"Asynchronous backend workflows for data processing",[103,372,373],{},"Modular backend architecture and API documentation",[103,375,376],{},"Interactive frontend development for real-time tournament participation",[89,378],{},[69,380,382],{"id":381},"impact","Impact",[74,384,385],{},"Bet.Monks gave Media.Monks employees a dedicated internal platform to participate in a tournament-long prediction competition, combining a polished user experience with reliable scoring and leaderboard updates throughout the FIFA Women's World Cup 2023.",{"title":387,"searchDepth":388,"depth":388,"links":389},"",2,[390,391,392,393,394,402,403,407,408],{"id":71,"depth":388,"text":72},{"id":93,"depth":388,"text":94},{"id":144,"depth":388,"text":145},{"id":153,"depth":388,"text":154},{"id":182,"depth":388,"text":183,"children":395},[396,398,399,400,401],{"id":187,"depth":397,"text":188},3,{"id":199,"depth":397,"text":200},{"id":226,"depth":397,"text":227},{"id":244,"depth":397,"text":245},{"id":262,"depth":397,"text":263},{"id":279,"depth":388,"text":280},{"id":308,"depth":388,"text":309,"children":404},[405,406],{"id":320,"depth":397,"text":321},{"id":338,"depth":397,"text":339},{"id":355,"depth":388,"text":356},{"id":381,"depth":388,"text":382},"md",false,{},true,"/projects/bet-monks-world-cup-predictions",{"title":5,"description":387},7,"projects/bet-monks-world-cup-predictions","Full-stack internal prediction platform for Media.Monks employees during the FIFA Women's World Cup 2023",[419,109,113,420,120,421,422,423,424,425],"Node.js","MongoDB","Quasar Framework","OAuth 2.0 (Google)","AWS S3","Simple Queue Service (SQS)","Swagger","T2CuRIbPOVkSCaxciJse2badAwM5L9nwlGIIqj6Wd90",1778044212351]