Live

Leaf Peek

Why Leaf Peek?

House plants and I have a complicated history. I’d find a lovely cultivar at a nursery, lovingly pot it at home and then, three weeks later, realise I’d been giving it the wrong light or watering schedule entirely. There was never a shortage of “plant identifier” apps – most were either pay‑walled, harvested my images for who‑knows‑what or delivered wildly inaccurate guesses that turned my peace lily into a philodendron overnight. Eventually I stopped ranting at my monstera and asked myself: rather than complain, why not build a tool that actually works?

That thought led to Leaf Peek, a small side‑project that marries my fascination with AI and my inability to remember Latin names. It’s not just a “find‑out‑what-plant-this-is” gimmick; it’s an attempt to create a gentle introduction to computer vision and generative AI for anyone who enjoys greenery. You drag or drop a picture (or take one in situ) and, within moments, it attempts to tell you the common name, scientific name and key characteristics of the plant. In the process you learn how to keep your botanic companion alive and, hopefully, build a little more trust in modern AI.

How It Works

At its core, Leaf Peek uses an image‑to‑text pipeline. On the front‑end, there’s a straightforward drag‑and‑drop zone that accepts JPEG or PNG files under five megabytes. Behind the scenes the image is compressed for performance and sent to an API endpoint. The back‑end checks that you haven’t blown through your daily allowance – ten requests per user over a rolling twenty‑four‑hour window – using a cookie and a tiny MongoDB table. The actual identification is then handled by a generative model from Google’s Gemini family. The prompt asks it to produce a JSON object with fields such as “Common Name”, “Scientific Name”, “Growth Habit” and “Plant Health”. If the model thinks you’ve sent it a picture of a potholder rather than a pothos, it returns a polite error message.

You’ll notice that I emphasise JSON here. When I first started tinkering with generative models for classification tasks, I was amazed at how well they responded to structured prompts. Rather than parse free‑form paragraphs, I could extract values directly into a Vue component. It also meant I could add or remove attributes (soil type, preferred fertiliser, pruning advice) without re‑training anything, simply by adjusting the prompt.

What Makes It Different

There are plenty of commercially polished plant identification apps. Leaf Peek is a deliberately modest alternative. It’s free, runs entirely in your browser and doesn’t require a sign‑in. Upload or snap a photo and the analysis happens behind the scenes. For users who want to try it on the go, the upload field accepts camera input on mobile too. The AI responds with detailed attributes and care suggestions to help your plants thrive.

Security and privacy were a priority from the start. Many AI‑driven tools cache your uploads to train their models. Leaf Peek processes images in memory and never stores them permanently. If you’re concerned about data usage, you can see how many daily requests you have left on the homepage. And because the underlying model can occasionally misfire on rare species (a reality that even corporate products acknowledge), the site reminds you to take clear, well‑lit photos and offers guidance if it fails to identify a plant.

On the client side, network hiccups or model throttling can cause calls to the identification API to fail. To provide a more robust experience, Leaf Peek retries failed requests up to three times with an increasing delay:

// In the handleSubmit function
const maxRetries = 3;
const baseDelay = 2000; // Start with a 2‑second delay
let attempts = 0;

while (attempts < maxRetries) {
  try {
    const data = await $fetch("/api/identifyPlant", {
      method: "POST",
      body: formData,
    });
    // Success: store the result and break out of the loop.
    plantInfo.value = data.plantInfo ?? null;
    requestsRemaining.value = data.remaining ?? requestsRemaining.value;
    loading.value = false;
    return;
  } catch (err) {
    attempts++;
    // If this was the last attempt, surface a user‑friendly message.
    if (attempts >= maxRetries) {
      if (err?.statusCode === 503) {
        error.value =
          "The AI model is currently overloaded. Please try again later.";
      } else {
        error.value =
          "We're unable to identify the plant right now. Please try another image.";
      }
      loading.value = false;
      return;
    }

    // Specific handling for HTTP 503 and 429.
    if (err?.statusCode === 503) {
      const delay = baseDelay * attempts;
      await new Promise((resolve) => setTimeout(resolve, delay));
      continue;
    }
    if (err?.statusCode === 429) {
      error.value = "Daily limit reached. Please try again tomorrow.";
      limitReached.value = true;
      loading.value = false;
      return;
    }

    // Generic fallback: back‑off and retry.
    const delay = baseDelay * attempts;
    error.value =
      "An error occurred while processing your request. Retrying...";
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
}

A Few Highlights

Here are some of the reasons I’ve grown fond of this little project:

  1. Ridiculously simple to use. There’s no account creation, no adverts and no invasive trackers. Just drag, snap or select, and let the model do the heavy lifting.
  2. Meaningful insights, not just names. The model returns care tips, watering frequency and light preferences. It even assesses plant health, flagging potential disease or stress for follow‑up.
  3. Respect for your data. Images are processed in transit and disposed of immediately. You’re not training some anonymous mega‑model without your consent.
  4. Built‑in boundaries. A ten‑query daily limit encourages mindful use and prevents abuse. If the model is overloaded, Leaf Peek tells you to try again later rather than silently failing.

Lessons Learned

I expected the hard part to be the AI itself. In reality, the biggest challenges were ethical and practical. How do you avoid spamming an external API? You set per‑user request limits and implement exponential back‑offs when the service is overloaded. How do you stop a hobby project from morphing into an accidental data‑harvesting operation? You delete images as soon as you’ve processed them. And how do you keep expectations realistic? You explain up front that even the best models occasionally struggle with uncommon species.

There were plenty of surprises too. For instance, Google’s Gemini model happily produced structured JSON when prompted correctly, but sometimes included trailing commentary or superfluous keys. Parsing out the valid object and surfacing meaningful errors took more effort than writing the prompt itself. I also discovered that compressing photos client‑side before upload dramatically reduced latency, especially on mobile networks.

Beyond Leaf Peek

Leaf Peek isn’t a commercial product. It’s a learning exercise, a showcase and a gentle nod towards what’s possible when you combine modern front‑end frameworks with state‑of‑the‑art generative AI. That said, I’ve been delighted to receive feedback from friends and strangers alike who have used it to rescue mislabelled succulents and uncover the names of mysterious vines. The sign‑up form exists purely to share occasional updates; I don’t have a monetisation plan and never will.

If nothing else, building Leaf Peek has deepened my appreciation for the complexity of the natural world and the fragility of artificial systems that attempt to describe it. Perhaps it will encourage a few more people to pay attention to the leaves around them, to learn their names and stories, and to care for them just a little better.