# AI Gardener: Spend 30 Seconds Here. Spend the Rest Outside.

> Source: <https://dev.to/thecuriouslad/ai-gardener-spend-30-seconds-here-spend-the-rest-outside-2m9j>
> Published: 2026-10-08 07:05:36+00:00

This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass](https://dev.to/challenges/hacktoberfest-week1-2026-10-05)

## 
  
  
  What I Built

**AI Gardener — Spend 30 seconds here. Spend the rest outside.**

Most gardening apps and AI chatbots do the exact opposite of touching grass: they keep you glued to your screen reading long encyclopedias, tweaking complex trackers, or scrolling through walls of generic AI text. I built **AI Gardener** around a single rule: **spend 30 seconds on the screen to see today's exact physical action, then close the app and go outside into your garden.**

AI Gardener is an open-source, multimodal gardening companion powered by local open-weight models (`gemma3:4b` for structured reasoning and vision, and `nomic-embed-text` for 768-dimensional semantic embeddings via Ollama), grounded with MongoDB Atlas Vector Search, and deployed live on Render.

Instead of giving generic textbook advice, AI Gardener acts like a local agronomist that remembers your garden across days and weeks:

- 
**Go Outside — Today's Next Actions Card:** At the very top of the dashboard, a dedicated action card surfaces the single next physical task for each of your active gardens (up to 3 concurrent gardens per user). You check what to do today in 30 seconds, walk outside, do the work in the soil, and mark it Done.
- 
**Sequential Multi-Day Lifecycle Progression:** Tasks are completed in real-world chronological order (`Day 1` ,`Day 2` ,`Day 3` ...). Once you finish your current batch of 5 tasks, a`Done — Generate Next Plan` button unlocks, advancing your garden from`Day 1–5` to`Day 6–10` and transitioning your garden phase from`PLANTING` to`GROWING` and`MAINTENANCE` without ever repeating completed tasks.
- 
**Hyper-Local Climate and Crop Grounding:** Growing tomatoes in Gorakhpur during winter fog (Rabi season) requires completely different care than growing hibiscus in Shimla or okra in Pune during the monsoon. I grounded the system in 2,174 curated plant health records across 76 crops and 70 agro-climatic records sourced from ICAR-CRIDA district contingency plans and meteorological authorities.
- 
**Multimodal Leaf Photo Diagnosis:** When you are outside in your garden and notice yellow halos, leaf curl, or brown spots on a leaf, you snap a photo and upload it. Gemma 3's vision capability inspects the leaf, cross-checks our plant pathology and local climate vectors (such as morning fog increasing fungal blight risk), and automatically updates your daily task schedule with targeted recovery actions.

**Who is it for?**

Home gardeners, balcony and terrace growers, and beginners who want hyper-local, step-by-step physical tasks tailored to their exact city, square footage or pot count, daily sunlight hours, and season.

## 
  
  
  Demo

## 
  
  
  Code

## ✨ The Idea

Most AI tools keep you glued to a screen.

**AI Gardener flips that.**

You spend 30 seconds telling it about your garden. It gives you one clear task for today. You go outside, do it, come back, and optionally snap a photo of your plant. The AI analyzes the photo, checks its knowledge base for diseases or care tips, and gives you tomorrow's task.

**The screen is the shortest part of the experience.**

## 🎯 Prize Categories

| Category | How We Qualify | 
| 🏆 **Overall (Touch Grass)** | Spend 30 seconds on the screen, spend the rest outside — built on open-weight `gemma3:4b` and`nomic-embed-text` | 
| 🍃 **MongoDB Atlas** | 4 collections ( `garden_sessions` ,`users` ,`plant_health_knowledge` with 2,174 records,`climate_location_knowledge` with 70 records) + 768-dim | 

…

 
 
 
GitHub Repository: [https://github.com/the-curious-lad/ai-gardener](https://github.com/the-curious-lad/ai-gardener)

## 
  
  
  How I Built It

I built AI Gardener around a modular, provider-agnostic open-source AI architecture running `gemma3:4b` and `nomic-embed-text` locally on Ollama, backed by MongoDB Atlas for stateful session persistence and 768-dimensional vector retrieval, and hosted on Render.

### 
  
  
  1. Four-Stage Agentic Pipeline

Every user message or photo upload flows through four specialized stages:

- 
**Stage 1 — Intent-Aware Query Rewriter and Router (`queryRewriter.js`):** Combines` gemma3:4b` structured JSON extraction (validated with Zod schemas) with a deterministic regex signal extractor so explicit user inputs (cities, Indian states, sq ft/pots, sunlight hours, seasons, and plant names) are never dropped or re-asked. Initial garden planning requires all 5 essential context fields (plant, city/state, growing area, daily sunlight hours, and season), while general botany questions or photo observations bypass unnecessary context checks.
- 
**Stage 2 — Dual-Collection Hybrid Vector Retrieval (`knowledgeVectorSearch.js` and `climateVectorSearch.js`):** Converts the normalized query into a 768-dimensional vector using`nomic-embed-text` and queries two MongoDB Atlas collections in parallel:`plant_health_knowledge` (2,174 records across 76 crops) and`climate_location_knowledge` (70 district and agro-climatic zone records). For regional climate, it resolves a 4-tier geographic hierarchy: Exact Location Mapping -> Regional Climate -> Seasonal Context -> Country/Zone Fallback.
- 
**Stage 3 — Multimodal Photo Reader (`photoReader.js`):** Uses` gemma3:4b` vision to extract structured symptoms (`visibleSymptoms` ,`leafCondition` ,`possiblePestSigns` ,`possibleDiseaseSigns` ,`severity` , and`confidence` ) from uploaded leaf photos, feeding those visual findings directly into the vector search and planner.
- 
**Stage 4 — Phase-Aware Planner (`plannerService.js`):** Synthesizes user context, retrieved agronomic records, climate constraints, and completed task history to generate sequential daily tasks (`Day 1` to`Day 5` , then`Day 6` to`Day 10` , etc.) and manage lifecycle transitions (`PLANTING` ->`GROWING` ->`MAINTENANCE` ).

### 
  
  
  2. Multi-Layer Domain and Input Guardrails

Small 4B parameter models can easily get derailed if a user enters impossible physical numbers, fictional places, or prompt injections. I built 5 deterministic guardrail layers around the Query Rewriter and Planner:

- 
**Guardrail 1 — Off-Topic, Length, and Prompt-Injection Fast-Path (0 LLM Calls):** Non-gardening queries (coding, sports, finance, cooking recipes), messages exceeding the 600-character limit, and prompt-injection attempts (such as "ignore previous instructions" or "reveal system prompt") are intercepted and refused in under 1 millisecond with zero LLM calls.
- 
**Guardrail 2 — Physical Sunlight Bounds Validation (1 to 16 Hours):** If someone enters an impossible value like 100 hours of daily sunlight or 0 hours, the guardrail rejects the invalid number while preserving the rest of their valid context, reminding them that a day only has 24 hours and asking for a realistic 1 to 16 hour daily sunlight figure.
- 
**Guardrail 3 — Knowledge-Base Location Verification:** If a user enters an unrecognized or fictional place (like "Atlantis") that is not in our climate knowledge base, the system strips the invalid location and transparently asks the user for a supported city or Indian state instead of hallucinating climate data.
- 
**Guardrail 4 — Supported Plant Verification:** Every requested plant is checked against our 76 verified CSV crops and supported Indian garden/ornamental plants. If someone asks to grow a non-plant item or unsupported species, the guardrail catches it immediately and suggests supported vegetables, herbs, fruits, and flowers.
- 
**Guardrail 5 — Agronomic Low-Sunlight Mismatch Warnings:** When a user plans a sun-loving crop (such as tomato, sunflower, chilli, hibiscus, or rose) with less than 4 hours of daily sunlight, the Planner automatically prepends a Sunlight Heads-Up warning advising them to place movable containers in their brightest south- or west-facing spot.

### 
  
  
  3. Bounded Context Summarizer for Small Local Models

Feeding an ever-growing chat history into a local 4B model quickly degrades instruction following and increases latency. I built a deterministic Context Summarizer (`contextSummarizer.js`) that maintains a compact 7-line structured memory summary (`contextSummary`) inside MongoDB while preserving the full raw `conversationHistory` in the database. Every AI prompt receives only the compact summary plus the last 4 messages, keeping token counts flat and inference fast even after dozens of turns.

### 
  
  
  4. Engineering for Latency, Streaming Resilience, and a 371 MB -> 114 MB Memory Optimization

Running an AI + Vector Search backend on Render's 512 MB RAM tier alongside a tunneled local Ollama instance surfaced real production challenges that I solved during development:

- 
**Cutting Memory Usage from 371 MB to 114 MB (69% Reduction):** Initially, Render was crashing with HTTP 502 Out-Of-Memory errors. Profiling heap memory revealed that parsing our 9.2 MB`plant_health_knowledge.csv` fallback file character-by-character (`currentField += ch` ) created millions of V8`ConsString` sliced string references, ballooning heap + RSS memory to 371 MB. I rewrote`parseCSV` in`src/utils/csvParser.js` using zero-copy index slicing (`content.slice(fieldStart, i)` ) and flat UTF-8 buffer allocation, dropping CSV memory footprint from 371 MB down to 114 MB.
- 
**Progressive Filter Relaxation in Vector Search:** Instead of loading all 2,174 documents into Node.js memory when a strict metadata filter returned 0 hits, I implemented progressive filter relaxation directly in MongoDB (`plant + knowledgeTypes` ->`plant only` -> bounded 200-document slice), keeping steady-state vector search RAM at just 63 MB.
- 
**Streaming NDJSON + Truncated JSON Auto-Repair:** When`gemma3:4b` generated long 5-day plans over a tunnel, waiting for a single non-streamed HTTP response caused proxy idle timeouts. I switched`OllamaProvider` to stream NDJSON tokens continuously (`stream: true` ), added automatic brace/quote stack balancing (`repairJsonCandidate` ) to recover truncated JSON outputs, and added a 24/7 hybrid deterministic fallback so the live Render app stays 100% functional even when my local laptop GPU is offline.

## 
  
  
  Why Does Open Innovation Matter?

Building AI Gardener on open-weight models (`gemma3:4b` and `nomic-embed-text`) via Ollama proved four major advantages over closed proprietary APIs:

1. 
**True Multimodal Privacy for Home Photos:** When users take photos of their backyard, balcony, or living space to diagnose a plant leaf, those images are processed on open weights under my control rather than being uploaded to a commercial third-party training pipeline.
2. 
**Zero Per-Token Cost for Multi-Step Agent Loops:** Each garden plan or photo diagnosis runs multiple structured steps (Query Rewriter -> 768-dim Embedding -> Dual Vector Retrieval -> Multimodal Vision -> Phase Planner). With open weights running locally on Ollama, iterating across hundreds of test turns and multi-day replans cost $0.00 in API fees.
3. 
**Deterministic Control Over Small Models:** Because I could inspect every raw token stream from`gemma3:4b` , I was able to build custom JSON stream repair, bounded 7-line context summarization, and domain guardrails that make a compact 4B open model perform reliably on consumer hardware.
4. 
**Hybrid Edge + Cloud Resilience:** By combining a cloud web host (Render) and cloud vector database (MongoDB Atlas) with a tunneled local Ollama inference engine and deterministic agronomy fallbacks, the project demonstrates how solo developers can ship zero-cost, open-weight AI web apps to production.

## 
  
  
  My Agent Session

During my agentic pair-programming session in Google Antigravity, AI Gardener evolved from a basic single-session chat prototype into a hardened, production-grade multi-garden platform. Here is a summary of what our initial prototype looked like and the key engineering changes we made together:

1. 
**From Single Chat Prototype to Multi-Garden Lifecycle Management:** We started with a single-session chat prototype, then redesigned the architecture to support lightweight user accounts, up to 3 concurrent gardens per user, a unified "GO OUTSIDE — TODAY'S NEXT ACTIONS" card across all active gardens, and strict sequential task completion (`Day 1–5` ->`Done — Generate Next Plan` ->`Day 6–10` ).
2. 
**Solving the Day 6+ Replan & Phase Regression Bug:** When testing multi-week progression, we noticed`gemma3:4b` sometimes repeated`Day 6` labels or reset the phase back to`PLANTING` on Day 6. We re-engineered the Planner prompt and deterministic post-processor to filter out completed task titles, enforce monotonic day numbering (`startDay + idx` ), and advance phases cleanly from`PLANTING` ->`GROWING` ->`MAINTENANCE` .
3. 
**Debugging Render's 512 MB OOM Crash (371 MB -> 114 MB):** When deploying to Render, the server hit HTTP 502 Out-Of-Memory restarts. We profiled Node.js`process.memoryUsage()` step-by-step, discovered that character-by-character CSV parsing on the 9.2 MB knowledge base was allocating 371 MB of V8`ConsString` objects, and rewrote the parser with zero-copy slicing to bring memory down to 114 MB (and 63 MB steady-state during vector search).
4. 
**Fixing Proxy Timeouts with NDJSON Streaming & JSON Repair:** Long structured outputs from local`gemma3:4b` over a Cloudflare tunnel occasionally timed out or truncated mid-JSON. We switched`OllamaProvider` to continuous NDJSON streaming, built a stack-based JSON auto-repair utility (`repairJsonCandidate` ), and added a clean one-click`Retry Sending` button in the UI.
5. 
**Hardening Security & Adding 5 Domain Guardrails:** In our final pass, we removed the internal Pipeline Inspector from the client UI so raw server state is never exposed, added a 600-character input cap, and built 5 domain guardrails so unrealistic inputs (like "100 hours of sunlight" or unknown cities/plants) are caught and explained gracefully.

## 
  
  
  Prize Categories

- 
**Overall Challenge Winner — Week 1: Touch Grass (Open-Source AI Innovation):** Built from the ground up with open-weight models (`gemma3:4b` and`nomic-embed-text` via Ollama) around the core motto "Spend 30 seconds here. Spend the rest outside." — turning local agro-climatic data, 2,174 plant pathology records, and leaf photos into immediate daily physical tasks in the garden.
- 
**Best Use of Gemma:** Uses`gemma3:4b` as both its structured JSON reasoning router/planner and its multimodal vision engine for leaf disease diagnosis, enhanced with custom JSON stream repair, 5 domain guardrails, and a bounded 7-line context summarizer designed specifically for a 4B parameter context window.
- 
**Best Use of Render:** Deployed live on Render ([https://ai-gardener.onrender.com](https://ai-gardener.onrender.com) ) and engineered specifically for Render's 512 MB RAM environment by reducing CSV parser memory from 371 MB to 114 MB, streaming NDJSON chunks to prevent proxy timeouts, and providing a 24/7 hybrid fallback.
- 
**Best Use of MongoDB Atlas:** Uses MongoDB Atlas across 4 collections (`garden_sessions` ,`users` ,`plant_health_knowledge` , and`climate_location_knowledge` ), combining stateful multi-garden lifecycle persistence with 768-dimensional`$vectorSearch` retrieval across 2,174 plant health records and 70 hierarchical climate records.

Thank you to the DEV team, MLH, DigitalOcean, Google DeepMind, Render, and MongoDB for hosting Hacktoberfest 2026 and championing open-source AI! Building this project solo was an awesome learning experience — now it is time for me to close my terminal, step outside, and touch some grass. 🌱
