[{"data":1,"prerenderedAt":207},["ShallowReactive",2],{"case-study-pony-academy-en":3},{"id":4,"title":5,"body":6,"description":173,"extension":174,"featured":175,"interactive":176,"meta":177,"navigation":175,"path":178,"seo":179,"stem":180,"subtitle":181,"tags":182,"technologies":189,"__hash__":206},"caseStudiesEn\u002Fcase-studies\u002Fen\u002Fpony-academy.md","Pony Academy — Riding School Booking Platform",{"type":7,"value":8,"toc":163},"minimark",[9,14,18,21,30,37,41,44,47,50,56,60,63,66,69,72,76,79,131,134,138,141,144,147,150,154,157,160],[10,11,13],"h2",{"id":12},"the-project","The project",[15,16,17],"p",{},"Pony Academy offers individual riding lessons for children. For a parent, booking starts with understanding the experience: how a lesson works, what equipment is provided, and how the instructor supports the child. For the school, every booking must fit a real schedule shared by instructors and horses.",[15,19,20],{},"I built the public website and the Pony Academy booking module on my Aurum framework. The scope connects a bespoke frontend with availability, bookings, payment integration, customer access, and an administration interface.",[15,22,23],{},[24,25,29],"a",{"href":26,"rel":27},"https:\u002F\u002Fponyacademy.pl\u002F",[28],"nofollow","Visit Pony Academy",[15,31,32],{},[33,34],"img",{"alt":35,"src":36},"Pony Academy homepage, with lesson information and a clear booking call to action","\u002Fcase-studies\u002Fpony-academy\u002Fmain.avif",[10,38,40],{"id":39},"a-calm-path-from-discovery-to-booking","A calm path from discovery to booking",[15,42,43],{},"The website introduces the first lesson before asking the parent to commit. It brings together the lesson structure, safety information, instructor profile, offers, and frequently asked questions, with a clear route into booking.",[15,45,46],{},"The booking journey breaks a complex decision into six steps: offer, date, instructor, horse, contact details, and payment. The interface presents availability through the booking API rather than asking the visitor to reconcile separate calendars. It supports guest booking as well as customer accounts; creating an account is optional.",[15,48,49],{},"The frontend uses Nuxt, Vue, TypeScript, and Pinia. Booking, account, and content integrations have their own module boundaries, so presentation components do not need to own scheduling or payment rules.",[15,51,52],{},[33,53],{"alt":54,"src":55},"Pony Academy booking entry, showing optional customer accounts and the six-step booking journey","\u002Fcase-studies\u002Fpony-academy\u002Fbooking.avif",[10,57,59],{"id":58},"scheduling-two-resources-at-once","Scheduling two resources at once",[15,61,62],{},"A lesson requires both an instructor and a suitable horse. A free instructor does not make a slot bookable if the horse is unavailable, already booked, or needs a break.",[15,64,65],{},"I modelled availability around instructor schedules, horse blackouts, existing bookings, lesson duration, and horse workload rules. The calendar derives valid slots from these inputs instead of storing a second, potentially inconsistent calendar of bookable times.",[15,67,68],{},"The backend also protects against simultaneous requests. Creating a temporary hold and changing a resource schedule use the same resource-and-day locks within a database transaction. This makes conflicts a server-side business rule, even when two visitors or an administrator act at the same time.",[15,70,71],{},"The scheduling domain remains independent of Vue, HTTP, database drivers, and payment providers. That separation lets the same rules serve the public booking flow and administrative operations.",[10,73,75],{"id":74},"payments-as-a-booking-lifecycle","Payments as a booking lifecycle",[15,77,78],{},"A redirect back from checkout is not proof that a lesson has been paid for. The payment-return screen reads the booking state and distinguishes confirmed, pending, and failed outcomes.",[80,81,82,95],"table",{},[83,84,85],"thead",{},[86,87,88,92],"tr",{},[89,90,91],"th",{},"Situation",[89,93,94],{},"System behaviour",[96,97,98,107,115,123],"tbody",{},[86,99,100,104],{},[101,102,103],"td",{},"A customer starts checkout",[101,105,106],{},"Temporarily hold the selected resources and create checkout using an idempotency key.",[86,108,109,112],{},[101,110,111],{},"A payment notification is repeated",[101,113,114],{},"Apply the booking change once using a transactional event inbox.",[86,116,117,120],{},[101,118,119],{},"A hold expires before payment arrives",[101,121,122],{},"Handle the late payment through a durable refund intent.",[86,124,125,128],{},[101,126,127],{},"A customer returns from checkout",[101,129,130],{},"Read the booking state before showing confirmation.",[15,132,133],{},"The browser can retain the booking hold session for recovery after a refresh. Hold expiration, payment events, and cancellation policies remain under backend control. Notifications and reminder scheduling are recorded alongside booking changes, keeping follow-up work tied to the committed booking state.",[10,135,137],{"id":136},"aurum-for-operations-aurora-for-content","Aurum for operations, Aurora for content",[15,139,140],{},"The Pony Academy module integrates with Aurum's Payments, Customers, Notifications, Storage, and Translations contracts. The school administration interface brings together offers, horses, instructors, availability, blackouts, bookings, and notification settings.",[15,142,143],{},"Customer identity belongs to the Customers module. A booking keeps its own historical contact and offer snapshots, while verified accounts can access their associated reservations. This keeps the lesson record understandable even when customer or offer details change later.",[15,145,146],{},"Aurora provides visual editing for website copy and images. The embedded site sends editing intentions to a trusted parent application, which authorizes and saves changes; the public frontend does not hold administrative tokens. Published content is loaded during server rendering, with defined fallbacks if the content service is unavailable.",[15,148,149],{},"This project extends Aurum beyond property websites: shared platform services support a different business domain while the public website retains its own identity.",[10,151,153],{"id":152},"validation-and-engineering-outcome","Validation and engineering outcome",[15,155,156],{},"The booking code includes tests for resource conflicts, simultaneous holds and blackouts, permissions, payment idempotency, and scheduling boundaries. Payment scenarios can use a local fake provider, allowing failure paths to be exercised without real transactions.",[15,158,159],{},"The public website and booking entry are live. The engineering outcome is a connected product: parents can discover lessons and enter a guided booking journey, while the implementation gives the school a common model for resources, reservations, payments, and communication.",[15,161,162],{},"The central design decision was to keep business rules in the booking domain and shared capabilities in Aurum. That gives the frontend room to evolve without duplicating the rules that protect the school's schedule.",{"title":164,"searchDepth":165,"depth":165,"links":166},"",2,[167,168,169,170,171,172],{"id":12,"depth":165,"text":13},{"id":39,"depth":165,"text":40},{"id":58,"depth":165,"text":59},{"id":74,"depth":165,"text":75},{"id":136,"depth":165,"text":137},{"id":152,"depth":165,"text":153},"A custom Nuxt website and Aurum booking module that connect lesson discovery, horse and instructor availability, online payments, customer accounts, and school administration.","md",true,false,{},"\u002Fcase-studies\u002Fen\u002Fpony-academy",{"title":5,"description":173},"case-studies\u002Fen\u002Fpony-academy","A welcoming website backed by resource-aware scheduling and Aurum",[183,184,185,186,187,188],"Aurum","Nuxt","Booking Systems","Domain-Driven Design","Payments","Vue.js",[190,192,194,197,200,203],{"name":184,"icon":191},"logos:nuxt-icon",{"name":188,"icon":193},"logos:vue",{"name":195,"icon":196},"TypeScript","logos:typescript-icon",{"name":198,"icon":199},"Node.js","logos:nodejs-icon",{"name":201,"icon":202},"MongoDB","logos:mongodb-icon",{"name":204,"icon":205},"Tailwind CSS","logos:tailwindcss-icon","9wgQ1l2LGkWc7j0fsMHL96gj1Eei-cS1PVdT3AfYSW8",1793020436143]