Case study · Ruta
What I've built inside Ruta.
Ruta is service-management software for landscaping and maintenance businesses — one platform carrying a job from the first rate request to the final payment. I did not start it, and it is not my company. I helped build it: since April 2026 I have shipped across all four of its apps and the AWS backend they share.
- Merged pull requests
- 400+
- Working on it since
- April 2026
- Apps I ship in
- Four
- Platforms
- Web, iOS + Android
Four apps over one backend
An owner, a crew member, and a homeowner want completely different things from the same job, so each has their own app over shared data. I work in all four, which is the reason a single change of mine often touches the backend, the office screen, and the field screen in one pull request.
Office web app
Owners and dispatchers
Customers, services, the schedule, dispatch, revenue, messaging, and a map of every property being served today.
Crew app
Field crews, iPhone and Android
Published as Ruta Crew. The day’s queue, the time clock, visit notes and photos — and it keeps working when the signal drops.
Customer portal
Homeowners and property managers
Approve a rate, pay a balance, follow a payment plan, review past visits, and ask for more work.
Admin console
The Ruta team
Onboarding new companies, payment provisioning, and the internal tooling that keeps accounts healthy.
The screens I work in
The office app and the customer portal
Two React apps over the same data: the dispatcher's control room, and the self-service view a customer gets. Sketched here rather than screenshotted, because real customer data sits on every live screen.
The office home screen — the day's visits, revenue, who is clocked in, and what needs a decision now.
The customer portal — active services, a balance to pay, and more work to request.
The work
What I've shipped, by area
Every line below went into production. It is a sample, not the full list — four hundred merged pull requests do not fit on a page.
Billing and money
The part of the product where a bug costs someone real money, so it gets the most care.
- Payment plans that charge their installments automatically on the due date, with the plan and balance visible to the customer in the portal
- Failed card charges retried instead of quietly left unpaid
- Account credits that stop re-applying once they are exhausted
- Collecting a payment now marks every visit that contributed to it as paid
- One bundle price charged once, rather than per visit
- Projected revenue built from live service schedules, so an owner can see what the book of business is worth next month
The crew app in the field
A crew will abandon an app that loses their work. Most of this is reliability, not features.
- The clock survives network blips, and a visit timer survives the app being resumed
- Photo capture times and distances that tell the truth, and an undo for a photo deleted by mistake
- Failed visit moves reported to error monitoring instead of being swallowed
- Crew leaders can remove a clocked-in member, and dispatch a service from the field
- Services, options, and requested work visible on the visit screen, in plain text



The office web app
Where owners and dispatchers spend their day, and where most of my changes land.
- A messages inbox with unread and needs-response filters, drafts that survive a reload, and reusable message templates
- Visits placed on their actual property on the map, with customer detail on hover and every clocked-in crew member’s trail
- A review queue that recognizes skipped visits and clears an approved visit immediately
- The AI assistant reachable from anywhere in the app, able to send a customer their existing rate, and failing in plain English instead of raw error codes
- Dozens of smaller repairs: a dashboard that stays usable on a narrow window, a close button Safari would not show, counts that agree with the page they link to
The customer portal
Self-service that has to be understandable by someone who has never seen the product.
- Payment plan and outstanding balance shown to the customer
- Service inquiries with selectable reasons, and an optional note when modifying a service
- Deactivated services with past visits stay reachable instead of disappearing
- Accurate visit counts for unlimited plans, and correct labels for one-time and seasonal work
Backend and platform
The AWS side: the data model, the scheduled jobs, and the plumbing everything else sits on.
- Job-site geofences and work zones precomputed on the backend, and an alert to the office when a crew member stops sharing location mid-visit
- Employee STOP texts honoured as an SMS opt-out
- Scheduled service deactivations that actually run on their date
- Whole-property measurement from the customer profile, so area-based services are priced off real square footage
- Maintenance scripts that stop reporting success when they processed nothing, and endpoints that return the right status instead of a 500
AI, in production
I built Ruta AI into the product — and it does the work, not just the talking
Ruta AI runs on Amazon Bedrock and I shipped it across the web app, the backend, and the crew app. The point was never a chat box bolted to the corner of the screen: it answers from the company's own records, and it can act on what it finds.
What I shipped
- Answers grounded in the company’s own records — notes, reviews, and how-to guides found by natural phrasing rather than exact keywords
- It takes actions and navigates itself: send a customer their existing rate, explain why a visit was flagged for review and then act on it, move the user to the right screen
- Reply drafts written from that customer’s real history, which a person edits or regenerates before anything is sent
- @-mentions and help-me-write inside messaging, on the web and in the crew app
- Marketing campaign suggestions, and a suggested rate applied with a keystroke
- One global entry point, so it is reachable from anywhere in the app
- Failures that read as plain English rather than an HTTP status code
What that means for your software
The same work, pointed at your product. Tap to Tick has an AI money coach in it too, so this is the second product I have shipped it in.
Grounded in your data, not the internet
The useful version of this reads your own records and answers from them. That is a retrieval problem before it is a model problem, and it is most of the work.
Actions, with a person in the loop
Drafting, sending, approving, scheduling — the model proposes and a human confirms. Nothing irreversible happens on its own.
Built to fail politely
Timeouts, a model chosen per task rather than the most expensive one everywhere, and errors a member of staff can understand and act on.
AI in the workflow, not just the product
In Ruta that also means production errors explained by an agent into Slack, a plain-language impact summary on every pull request, and a system map so agents can find their way around the codebase.
How I work
Coming into a codebase someone else started
Ruta is the long-running example of what I do inside an existing product with a team around it — which is most client work. The habits matter more than the features.
Read first, then ship in its grain
I follow the conventions already in the repo rather than importing my own. A reviewer should not be able to tell which files are mine.
Small, reviewable changes
One ticket, one pull request, described in plain language. 400+ of them merged, which only works if each is easy to review.
Errors that say something
A lot of my work is turning silent failures and raw error codes into messages a dispatcher or a crew member can act on.
Careful around money and time
Billing, clock-ins, and scheduled jobs get the most scrutiny, because those are the bugs a business actually feels.
Built with
A TypeScript monorepo on AWS
One language end to end: React on the web, React Native through Expo on phones, and Lambda functions over DynamoDB behind them, with the infrastructure itself defined in code. Payments run through Justifi, maps through Mapbox, search through Typesense, and the assistant through Amazon Bedrock.
Have software that needs another pair of hands?
This is the work I do most: joining a live product and shipping in it without breaking what already works. Tell me what yours needs to do next and I'll scope it and send a quote.