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.

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.
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
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
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
How long it took
About two and a half months of intense building.
2.5 months · 5 sprints · 320 commits
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.