CCasey White
← All work
TPre-MVP

Tree Canopy

Walk the site. Talk the survey. Send the report.

Voice-first BS 5837 tree surveys for arborists who would rather be outside than at a desk.

Category
Field SaaS
Timeline
2.5 months · 5 sprints · 320 commits
Focus
Enterprise & field
Visit Tree Canopy ↗
Tree Canopy preview
01

Why I built it

I built this for arborists like Phil, the sole traders and tiny consultancies who know trees cold but hate software. They spend about 40% of their billable time stuck at a desk writing up reports after a day on site, hands full of clipboard, DBH tape, laser and camera the whole time. The existing tools are slow and desktop-rooted. I wanted to give these folks their afternoons back: walk the site, dictate each tree by voice, snap a photo, and walk away with the data already 80% report-ready. Then one tap turns the day's pins into a BS 5837-compliant PDF the client can actually pay for.

02

What it does for people

  • Voice-first field capture. Dictate a whole tree inspection hands-free while standing at the trunk, no typing on a tiny screen
  • One-tap BS 5837-compliant PDF report generation, with the narrative auto-drafted by AI so you edit and sign off instead of writing from scratch
  • Automatic Root Protection Area calculation to BS 5837:2012 spec, covering single-stem, multi-stem and veteran trees
  • Pl@ntNet species ID from a photo, giving top-three guesses with confidence pills
  • A time-saved banner and live time-per-tree HUD benchmarked against the industry 90-second baseline, so the value is something you can feel
03

Under the hood

  • A single multimodal Gemini Flash call turns a voice recording straight into structured BS 5837 JSON. I collapsed a two-pass Deepgram-plus-Claude pipeline into one vendor call routed through the Vercel AI Gateway, keeping it under a 10-second end-to-end rule with provider failover for free
  • Claude Haiku 4.5 does structured extraction and drafts the report narrative, with the option to swap up to Sonnet per call when accuracy matters more than cost
  • One Next.js 14 codebase wrapped with Capacitor ships web, Android and iOS from the same source. Every server concern is just a Next.js API route or a Supabase Edge Function
  • PDF reports rendered with @react-pdf/renderer, no Puppeteer, cached and warmed ahead of time
  • An offline-first, event-sourced sync layer designed up front: IndexedDB or SQLite locally, an idempotent /api/sync applying events under RLS. The genuinely hard part, spec'd before the easy stuff
04

The cool bits

  • It is voice-first, not voice-aided. The whole point is that you never touch the keyboard in the field
  • The time-saved toast on report generation literally tells you it just saved you nearly three hours, which is the whole pitch in one line
  • MapLibre and OpenFreeMap instead of Mapbox, so map loads cost nothing even when surveyors hammer the map all day, with native offline tile packs
  • Real brand polish: Fraunces, Inter and DM Mono, a forest and bark and paper palette, a custom logo, favicon and OG images
05

How long it took

About two and a half months of intense building.

2.5 months · 5 sprints · 320 commits

06

What I worked through

The single hardest problem is offline-first sync. Field surveyors are out in the woods with no signal, so I designed an event-sourced local store that queues everything and replays it through an idempotent sync endpoint into Postgres under RLS once a connection returns. I designed the whole thing up front but deliberately shipped v0 with the network path required rather than rush the conflict-resolution logic. The other big call was ripping out my original two-pass voice pipeline and betting on a single Gemini Flash multimodal call: simpler, cheaper, one billing relationship, and fast enough to stay under my 10-second rule.

07

The full stack

Next.js 14 (App Router)TypeScriptCapacitor (Android + iOS)Supabase (Postgres, RLS, Storage, EU region)Vercel AI GatewayGemini Flash (voice transcription + intent)Claude Haiku 4.5 (extraction + drafting)Pl@ntNet API (species ID)MapLibre + OpenFreeMap (offline tiles)@react-pdf/rendererRevenueCatPostHogSentry EUPWA / service workerpnpmVitestPlaywright