A garden grow log built around pinching — every plant carries the reason nipping out its tip pays off.

The problem

Gardening advice is written for a month. Your plant went in on a Tuesday.

Every guide tells you what to do in May. None of them know when you actually planted anything, so the advice arrives at the wrong time for your garden and you either act too early or find out too late. A grow log that only records the past is a diary; the useful part is what it tells you to do next week.

The other half is the photograph. Point a camera at a sick leaf and most tools hand back one confident species name and a treatment, which is the failure mode — a plant disease looks like three other plant diseases, and acting on the wrong one costs you the plant. Pinch is built so that its answer arrives with the things that would prove it wrong.

Never claim certainty from a single photo.

How it works

The pipeline, step by step

Nine steps, and the seventh is the one the app is really about. The rest is a grow log; that one is the reason to trust it.

  1. 01

    Add the plant, and the day it went out

    Ninety-seven plant types across ten categories, ten locations from garden bed to cold frame to allotment, four sun exposures and eight growth stages. The planting date is the field everything else keys off.

    plant_types.dart
  2. 02

    Every plant says why you'd pinch it

    Not a species list with a name and a photo. Each type carries what pinching that particular plant buys you — more blooms and bushier growth on a dahlia, delayed flowering on basil — and it is shown in the picker, at the moment you are choosing.

    pinchBenefit
  3. 03

    Tasks come off your date, not a calendar

    A nightly job walks every growing plant and materialises its care tasks from the day you planted it plus an offset. The reminder to stake a dahlia lands three weeks after it went into your soil, not in a generic article about June.

    plantOutAt + offsetDays
  4. 04

    One digest, at an hour you chose

    An hourly job sends only to people whose chosen hour it is, skips their quiet hours, and writes a per-day marker so it cannot send twice. A gardening app that pings you at ten at night is one you delete.

    withinQuietHours()
  5. 05

    Photograph it, and the phone stays out of the analysis

    The photo uploads once. A storage trigger derives a thumbnail and a medium copy server-side, and the model is handed a bucket reference rather than the image being sent a second time from the handset.

    onUserPhotoUploaded
  6. 06

    The model is asked for candidates, not an answer

    Identification returns the top three with the reasoning behind each, a confidence band written in words rather than a percentage, and three questions it wants you to answer before it commits any further.

    candidates (top 3), questions (3)
  7. 07

    The diagnosis arrives with the checks that would disprove it

    Triage cannot return a bare verdict — the response schema will not accept one. Alongside the likely issues it must return `confirm`: the signs you have to go outside and look for yourself. The app renders those as their own card, sitting between the diagnosis and the treatment, so you cannot reach what to do about it without scrolling past what might falsify it.

    confirm[] + "It can be wrong."
  8. 08

    Log what you actually did

    Eight event types, and they are the ones that matter to a grower rather than a generic note field: pinched, staked, fed, deadheaded, pest, disease, bud set, first bloom.

    add_event_page.dart
  9. 09

    Or let it draft the entries for you

    Photograph the plant and it proposes up to five timeline entries, each with the reason it thinks so and a plain-word confidence. You accept the ones that are right. It never writes to your log on its own.

    ≤5 suggestions, each with a reason

Honest by design

A plant doctor that hands you the checks, not the verdict.

The tempting product is the one that names the disease and tells you what to spray. Pinch will not do that, because a photograph of a leaf genuinely is not enough to be sure, and a confident wrong answer costs you the plant. Every answer it gives is shaped so you can go and test it.

  • Answers arrive as a shortlist with reasoning — never one confident name
  • Every diagnosis names the signs you must confirm yourself — never just a treatment
  • Confidence is written in words — never a meter that implies precision
  • It asks three questions back — never assumes it has enough to go on

To Confirm

Check the undersides of the leaves for colonies, and whether the spots spread after rain. Both would point away from the first candidate.

Before you treat anything

Illustrative

Everything inside

A whole world in one app

Ninety-seven plants, each with a reason to pinch it

The pinch benefit is the app's whole argument, and it is surfaced where the decision is made rather than buried in a help page.

Every plant says what pinching buys you — never a bare species list.

plant_types.dart

A plant doctor that shows its working

Identify a plant, diagnose a problem, or have it suggest what to log. Every mode answers with candidates, reasoning and the checks that would disprove it, and there is a free-text box for the context a photo cannot carry.

Answers come with the signs to confirm — never a single confident verdict.

likely_issues + confirm + escalate

Everything inside

The rest of it

Tasks off your planting date

Care, growth, problem and overwintering tasks generated from the day the plant went in. Snooze a day, three days, a week, or until a date you pick.

A digest that respects your evening

One push at the hour you chose, capped, quiet-hours aware, and deduplicated so a retry cannot send it twice.

A photo timeline per plant

Every photo kept at three sizes generated server-side, threaded onto one timeline with the events you logged, so a season reads as a sequence rather than a folder.

Loaders built rather than downloaded

Facet Bloom, Growth Ring and Facet Skeleton — three hand-written painters that carry the low-poly identity into the waiting states, plus a wind sway deliberately capped at a few degrees so it reads as breeze rather than animation.

Groups, with reporting that only goes one way

Public or private groups with posts, photos and comments. Reports are write-only by design — a member can file one and nobody, including other members, can read, edit or delete it.

Architecture

How it's put together

A Flutter client of roughly 23,000 lines, a small TypeScript Functions surface for anything scheduled or privileged, and a Python service that is the only thing permitted to talk to the model. Everything runs in London except the model itself.

App

Web and Android from one codebase
Flutter
Dart, web and Android from a single source
Riverpod
State, with the theme and accent persisted locally
GoRouter
Routing
CustomPainter
The three hand-built loaders and the sway animations

Backend

Cloud Functions, London region
Task generation
Nightly, materialising each plant's schedule
Digest
Hourly, quiet-hours aware, deduplicated per day
Image derivatives
Storage-triggered thumbnail and medium copies
Purchase check
Server-side entitlement, not yet wired to a store

AI

A separate service, so the app never holds a model credential
FastAPI on Cloud Run
Identify, triage and auto-log endpoints
Vertex AI
Gemini, with a schema the response has to satisfy
Firebase ID token
Verified server-side on every call
Low temperature
So the same photo answers with the same structure

Data

Firestore
Per-user subtrees; plant reference data is read-only
Cloud Storage
Originals plus the two derived sizes
FCM
The digest, and nothing else

Background

The story

Pinching is the horticultural act of nipping out a growing tip so the plant branches instead of running to a single stem. Do it to a dahlia and you get more blooms on a bushier plant; do it to basil and you delay it bolting. It is one of the highest-return things a gardener can do and it is almost never explained at the moment you are stood over the plant wondering whether to.

So that became the app. Every one of the ninety-seven plant types carries its own pinch benefit, shown in the picker rather than in documentation, and the name of the app is the thing it is trying to teach.

The task engine was the second decision. Anchoring care to a real planting date instead of a month is more work — it needs a nightly job walking every growing plant and materialising its schedule — but it is the difference between a log and something that earns its place on your phone.

The plant doctor was the hardest thing to get right, and the work went into making it less confident rather than more. It is prompted never to claim certainty from a single photograph, its answers are shaped by a schema that will not accept a bare verdict, and the signs that would disprove it are rendered as their own card in front of the treatment. That is slower to read than a species name and a spray, and it is the honest shape of the answer.

The look came from a written art direction rather than a component library — a low-poly, faceted identity carried down into three hand-built loaders and a wind sway capped at a few degrees, so the app moves like weather rather than like software.

Next

QR Protector

Check the code before you trust it