Cat Plants
Point your phone at a plant. Find out whether it can hurt your cat.
Identification only names the plant. The ASPCA list decides whether it's safe. PlantNet names the species; it knows nothing about cats. The safe/toxic call is a lookup against a bundled ASPCA-derived database that answers offline. An empty lookup returns "Not in our database — treat as potentially unsafe." No guessing, no language model.
Three Input Methods
Camera framing, on-device ML Kit tag OCR, or offline fuzzy name search. Wakes the cloud proxy when camera intent starts.
High-Contrast Signal Band
Red "KEEP AWAY" or green "ALL CLEAR" band, the matched name, and the clinical signs the ASPCA reports for that plant, with a link to the source row. Reference photo via Wikipedia, credited in the app.
Verify the Match
Safe verdicts show the matched row, the ASPCA's wording, and a credited reference photo to compare against the plant in front of you.
983
Plants in the list 423 toxic / 560 non-toxic3,214
Common-name aliases< 50ms
Offline search latency30.5 MB
arm64 release APKAsymmetric Failure Mode Design
A wrong "safe" is the failure mode that costs something. Every ambiguity resolves toward caution.
Decoupled Identification & Safety Authority
PlantNet identifies botanical names. It knows nothing about cats. The safe/toxic call is a map lookup against a bundled ASPCA-derived JSON database.
Toxic-Biased Genus Fallback
Most-specific name wins. An exact species match beats a genus-level row. An unlisted species in a genus with any toxic member resolves toxic. The original matcher let the first toxic fragment win; a sweep of the shipped dataset found 97 cases where that changed the verdict. The matcher was fixed and the sweep now runs as a test.
It Never Guesses
An unlisted or low-confidence result returns "Not in our database — treat as potentially unsafe." No fallback to a language model, no inferred verdict.
Technical Architecture
Flutter Background Isolate Index
Flutter / Dart983 plants and 3,214 aliases indexed once at load on a background isolate, so a lookup is a map hit rather than a scan — under 50ms, offline.
On-Device ML Kit Label Scanning
Google ML KitML Kit OCR reads nursery plant tags on-device. Runs offline; no network latency, no API key.
Serverless Azure Proxy & Pre-Warming
Dart / AzureDart `shelf` backend proxy gates API keys, hashes images for caching, and caps daily calls. Pre-warms container on camera-open intent to eliminate 17s cold start.
Release Binary Size Optimization
R8 / ABI SplittingPer-ABI release builds cut the APK from 79.4 MB to 30.5 MB by packaging only the arm64 ML Kit binaries.
Every verdict traces to its source
The plant list was rebuilt from the ASPCA's toxic and non-toxic plant pages: 983 plants, 423 toxic and 560 non-toxic, with 3,214 common-name aliases. Each row carries the ASPCA-reported clinical signs and a link to its source page. Nothing is paraphrased from memory.
Typed lookup — answered offline, from the bundled list.
27 real scans, every failure written up
27 scans in Central Park's Conservatory and Shakespeare Gardens, on a Pixel 8, in natural light. Findings are tagged as measured or verified after the fact. Each miscitation of the app's own dataset became a failing test before any fix. Write-ups: docs/conservatory-garden-field-findings.md in the repo.
Crapemyrtle by the fountain: ALL CLEAR, the walk photo beside the credited reference shot, the raw 62% ID confidence shown.
The confirm step on a bed of dahlias. Only this photo is sent for identification.
Current work: identifying plants by taxon rather than name string, so lookups key on what the plant is, not what a label calls it.
From Photo to Safety Verdict
Intent & Capture
Camera frames plant or OCR reads tag. Background ping wakes serverless Azure proxy from zero-scale state during framing.
Proxy Identification
Azure Container Apps Dart proxy verifies client token, checks SHA-256 image cache, and retrieves taxonomy name from PlantNet.
ASPCA Rule Evaluation
On-device isolate queries ASPCA dataset. Resolves toxic-biased fallback rules and renders high-contrast signal band.
What it doesn't do
It can be wrong about the plant.
PlantNet returns a confidence score and the app shows it, but a mediocre photo can still name the wrong species. That is why the compare screen exists.
The list is not exhaustive.
983 plants is not everything. "Not in our database" means unknown, not safe.
It is not veterinary advice.
It is a lookup against a public list. If your cat ate something, call your vet or the ASPCA Animal Poison Control Center (888-426-4435) — don't work it out from a phone screen.
Custom Mobile & Cloud Engineering
We bring mechanical and systems engineering discipline to mobile apps, IoT integrations, and cloud infrastructure.