Al Bunch

LawnWire — Field Service Management Platform

Mobile-first field service management with GPS time tracking and multi-fallback geocoding. Server-rendered with Hotwire — a deliberate alternative to the React SPA approach.

Symfony 6HotwireStimulusPostgreSQLTailwindMapboxDocker

A multi-tenant SaaS application for lawn care and landscaping businesses to manage operations from the field. Early-stage but architecturally complete — demonstrates a deliberately different technical approach from TC Track.

The Deliberate Stack Choice

TC Track is a React SPA because transaction coordinators work at desks all day in a complex, stateful UI. LawnWire is server-rendered with Hotwire/Stimulus because crews work on phones in the field — they need fast page loads on spotty connections, touch-friendly interactions, and minimal JavaScript payload. Same engineer, different tool for a different problem.

GPS-Powered Time Tracking

Crew members check in and out at client locations using phone GPS. The system records exact coordinates at both events, verifies workers are on-site, auto-calculates hours, and can find nearby clients based on current location (Haversine formula, 100m default radius).

Multi-Fallback Geocoding

Every client address is geocoded with lat/long coordinates. Rather than depending on a single geocoding service, the system chains four providers (Nominatim, Photon, LocationIQ, Nominatim Simple) so address lookups almost never fail.

Financial Precision

All invoice calculations use bcmath for arbitrary-precision arithmetic — no floating point errors on money. Invoice client data is denormalized at creation time so records stay accurate even if client info changes later (a pattern that matters for accounting and audits).

Architecture Patterns

  • SQL-level tenant isolation — Doctrine SQLFilter appends WHERE organization_id = ? to every query automatically
  • Soft deletes everywhere — clients, services, and organizations are deactivated rather than deleted to preserve billing and reporting history
  • Mobile-first, not responsive-as-afterthought — touch targets, card layouts replacing tables on small screens, overscroll containment, double-tap zoom prevention
  • Asset Mapper instead of Webpack/Vite — Symfony’s native asset pipeline, no Node.js build step required