Scapeboard is a full-stack landscaping business platform — property mapping, AI-powered design visualization, smart rate forecasting, invoicing, and route optimization. Everything a contractor needs, on the phone they already have.
The dashboard. Personalized, weather-aware, project-driven.
Landscaping contractors typically cobble together separate tools for quoting, invoicing, scheduling, routing, and client communication — none of which talk to each other. The result is data entry duplication, missed follow-ups, and proposals that take longer to write than the job takes to do.
Scapeboard collapses all of it into one platform. Build a proposal from your service catalog, generate an AI visualization of the finished yard, send the invoice, then optimize the day's route — all without leaving the app. The data flows because it lives in one place.
Gemini generates photorealistic renderings of the finished landscape from property photos and a description — before a single plant hits the ground.
Google Maps integration lets you measure square footage, annotate zones, and plan planting areas directly on a satellite view of the property.
AI-powered rate suggestions based on job type, materials, and labor markup. The system learns your margin targets and flags pricing inconsistencies.
Full project lifecycle from proposal to close — line-item estimates pulled from your service and material catalog, markup controls, and PDF export.
Client-ready invoices generated from project data. Track receivables, collected amounts, and outstanding payouts in a live finance dashboard.
Multi-stop route optimization for the work day. Load stops from your project list, set your origin, and let the engine sequence the most efficient path.
Centralized libraries for services, materials, and plants. Set base costs, configure markup targets, and pull items directly into any estimate.
$12.99/month or $14.99 one-time 30-day access unlocks 50 AI image generations per month. Billed through Stripe on web and Google Play Billing on Android.
Rapid proposal drafting on the fly — search your catalog, set quantities, and build a clean high-precision landscape proposal in under two minutes.
The standout feature of Scapeboard is its AI visualization pipeline. A contractor uploads reference photos of the property, describes the desired design, and Gemini generates a photorealistic aerial rendering of what the finished landscape will look like.
This isn't decoration. The images serve as a proposal tool — something a contractor can show a client to close the job before ever pulling out a measuring tape. The property's scale data (sq ft breakdown by zone) sits alongside the visual so the numbers and the picture tell the same story.
Reference photos uploaded to the project ground the AI generation in reality — the model sees the actual house, the actual lot shape, the actual lighting — producing results that feel specific rather than generic.
AI-generated aerial rendering. Property scale: 12,059 sq ft across four zones.
Every screen is designed for a contractor on a job site — large touch targets, clear hierarchy, no friction between the task and the tap.
Scapeboard is the most architecturally complex thing I've shipped. A React frontend, an Express backend on Cloud Run, Firebase Auth and Firestore, two billing systems, a Maps SDK, and a generative AI pipeline — all coordinated through a single Capacitor-wrapped Android app. Here's what actually happened.
Landscaping contractors aren't product people. They're not going to read a tooltip or dig through a settings menu. Every screen in Scapeboard had to be self-explanatory on first contact — section titles that describe the screen's purpose directly (Services Library, Dispatch Engine, Quick Estimate Workspace), empty states that tell you exactly what to do, and a dashboard that surfaces the three numbers that actually matter: active projects, pipeline revenue, and outstanding invoices.
The Google UX Design certificate did real work here. Audience empathy isn't abstract when the audience is someone who'd rather be outside than on their phone.
Most indie developers ship one billing path and bolt on the second later. I wanted both working at launch. The problem: Stripe and Google Play Billing have completely different webhook lifecycles, entitlement schemas, and failure modes.
The Firestore entitlement document became the source of truth — a single record per user
with plan, proSince, proExpiry,
billingSource, and imageGenerationsUsed fields, written to by
whichever billing system triggered the webhook. The client never talks to Stripe
or Play directly — it reads Firestore. That abstraction is what made dual billing
tractable.
Deploying secrets to Cloud Run via gcloud on Windows is a trap. The standard
echo MY_SECRET | gcloud run services update --set-secrets pattern silently
appends a BOM (byte order mark) or trailing newline to the secret value, which then fails
at runtime in ways that look nothing like an encoding problem.
The fix: write secrets using PowerShell's
System.IO.File::WriteAllText with UTF8Encoding($false) and
explicit no-newline to produce clean byte sequences. A subtle platform quirk that cost
a full debugging session before the pattern clicked.
applicationDefault() — the standard Firebase Admin initialization path —
doesn't work reliably in Cloud Run without explicit configuration. The webhook would
receive Stripe events successfully, then fail silently trying to write to Firestore
because Admin couldn't authenticate.
The fix was a service account JSON stored in Secret Manager, injected at runtime and parsed explicitly by the Admin SDK — more setup, but zero ambiguity about what credentials are in play. Once the pattern was established it became the standard for every sensitive credential in the project.
Google Sign-In in a Capacitor app works fine on localhost. Against a production domain
it requires the correct SHA-1 fingerprints registered in the Firebase console, the right
google-services.json, and the authorized domain whitelisted in Firebase Auth
settings — three separate places that all have to agree.
The debugging surface is also deceptive: auth errors from the native layer surface as
generic auth/unauthorized-domain even when the domain is authorized
but a fingerprint is wrong. Tracking down which of the three layers was out of sync
required eliminating them one at a time.