The Stakeholder Challenge
Managing a fleet of 12 rental vehicles in Sydney with Google Sheets, WhatsApp messages, and manual bank statement reconciliation. Every week, each renter owed $300-450. The job: track who owes what, send reminders, collect payments, reconcile records.
The breaking point: 11 PM on a Wednesday, reconciling payments, realising we'd double-counted one renter while missing another entirely. Payments weren't just late โ they were invisible. Bank transfers showed as random amounts from random names. Matching them was a 45-minute weekly exercise that still produced errors.
The business cost: - 3-4 hours per week on manual reconciliation - Average of $1,800/month in "lost" payments that were actually uncollected due to tracking failures - Two renters who genuinely stopped paying went unnoticed for 3 weeks because the spreadsheet data was unreliable - No system for overdue alerts, payment history, or renter communication
The Stakeholders
The Technical Decisions
Why Next.js App Router? Speed-to-market. We'd built multiple projects on Next.js โ the tooling, deployment, and developer experience were familiar. For a SaaS where shipping in weeks matters more than architectural perfection, pick the tool you're most productive in.
Why PostgreSQL over NoSQL? Fleet management data is inherently relational. Vehicles have many rentals. Rentals belong to one customer. Payments belong to one rental. Postgres handles these relationships cleanly with foreign keys, joins, and constraints that prevent the data inconsistency that plagued the spreadsheet.
Why Stripe Payment Links over full embedded checkout? The entire point was eliminating bank transfer chaos. Full checkout with saved cards and recurring billing would have added two weeks of development. Stripe Payment Links achieved 90% of the outcome with 10% of the effort: generate a unique link per renter per week, email it on due day, payment recorded automatically via webhook.
Why Resend for email? Every week on the renter's due day, the system sends an email with their payment link. Unpaid after 48 hours? Automatic reminder. 7 days overdue? Escalation email to the fleet owner. This replaced the Monday morning WhatsApp ritual entirely.
The 21-Day Build
Week 1 โ Core CRUD (Days 1-7)
Vehicle management: add, edit, remove vehicles with make, model, registration plate, status. Customer management: renter profiles with contact details and document references. Rental creation: assign vehicle to customer with weekly amount and payment schedule.
No styling beyond Tailwind defaults. Just forms that worked. Every evening, we dogfooded by entering our own fleet data. By day 5, the database already had more accurate records than the spreadsheet.
Week 2 โ Payments (Days 8-14)
Stripe integration, webhook handling, automated email pipeline. This was the hardest week.
The critical challenge: Stripe webhooks in development vs. production. Webhooks work differently when testing locally with stripe-cli vs. receiving production events. We burned a full day debugging a webhook that worked in test but failed in production because of a Stripe API version mismatch.
Key architecture decision: handle payment_intent.succeeded idempotently. Stripe retries failed webhook deliveries, so the same payment event might arrive 3-4 times. Without idempotent handling, that's duplicate payment records.
Also built the owner dashboard: fleet size, active rentals, this week's payments, this month's revenue, outstanding balance, overdue alerts. The screen fleet owners live on.
Week 3 โ Polish and Launch (Days 15-21)
Customer portal for renters to view their rental details and payment history. Overdue reminder emails (48-hour and 7-day). Receipt generation. Mobile responsiveness โ most renters check email on phone, so payment emails and Stripe checkout had to be pixel-perfect on mobile.
Migration Day
Day 21. We migrated our 12-car fleet off Google Sheets. Entered all vehicles, customers, and active rentals. Set up weekly payment schedules.
First automated emails went out Tuesday morning. By Thursday afternoon, 9 of 12 renters had paid via Stripe link โ without a single WhatsApp message, bank transfer, or manual reconciliation.
The Monday morning payment chase ritual was over.
Results After 90 Days
Stakeholder Impact
For fleet operators: Payment collection that runs on autopilot. Log in Monday morning to a dashboard showing who's paid, who's overdue, and what's coming in this week. No spreadsheet. No WhatsApp. No bank statement archaeology.
For renters: A clean portal showing their rental details, payment schedule, and history. One-click payment via Stripe link in their email. No more memorizing BSB numbers or putting reference codes in bank transfers.
For us as a business: RentalsCube proved the model โ build software to solve your own problem, then offer it to everyone with the same problem. The product now serves fleet operators across Australia, and the subscription revenue covers its own infrastructure costs.
What We'd Build Differently
Recurring Stripe subscriptions from day one. Payment links require renters to click every week. Subscriptions with saved cards would automate even further. We avoided this in v1 to ship faster, but it's the most-requested feature.
SMS alongside email. Some renters don't check email reliably. SMS payment reminders would have caught the remaining 6% of late payments.
Multi-currency support. Not needed for Australia, but early international interest means we'll need AUD/NZD/USD eventually.
None of these gaps were worth delaying launch. Every one was identified by actual users in production โ which is exactly the point of shipping fast.