This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
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, aDone โ Generate Next Planbutton unlocks, advancing your garden fromDay 1โ5toDay 6โ10and transitioning your garden phase fromPLANTINGtoGROWINGandMAINTENANCEwithout 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
- Live Deployed Application (Render): https://ai-gardener.onrender.com
- Screenshots / Demo Video:
Code
๐ฑ AI Gardener โ Touch Grass
Hacktoberfest 2026 ยท Week 1
An open-source AI gardening assistant that gets you off the screen and into the soil.
โจ 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
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): Combinesgemma3:4bstructured 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.jsandclimateVectorSearch.js): Converts the normalized query into a 768-dimensional vector usingnomic-embed-textand queries two MongoDB Atlas collections in parallel:plant_health_knowledge(2,174 records across 76 crops) andclimate_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): Usesgemma3:4bvision to extract structured symptoms (visibleSymptoms,leafCondition,possiblePestSigns,possibleDiseaseSigns,severity, andconfidence) 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 1toDay 5, thenDay 6toDay 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.csvfallback file character-by-character (currentField += ch) created millions of V8ConsStringsliced string references, ballooning heap + RSS memory to 371 MB. I rewroteparseCSVinsrc/utils/csvParser.jsusing 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:4bgenerated long 5-day plans over a tunnel, waiting for a single non-streamed HTTP response caused proxy idle timeouts. I switchedOllamaProviderto 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:
- 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.
- 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.
-
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. - 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
- Full Agent Session Log (GitHub): https://github.com/the-curious-lad/ai-gardener/blob/main/AGENT_SESSION.md
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:
-
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). -
Solving the Day 6+ Replan & Phase Regression Bug:
When testing multi-week progression, we noticed
gemma3:4bsometimes repeatedDay 6labels or reset the phase back toPLANTINGon 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 fromPLANTING->GROWING->MAINTENANCE. -
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 V8ConsStringobjects, and rewrote the parser with zero-copy slicing to bring memory down to 114 MB (and 63 MB steady-state during vector search). -
Fixing Proxy Timeouts with NDJSON Streaming & JSON Repair:
Long structured outputs from local
gemma3:4bover a Cloudflare tunnel occasionally timed out or truncated mid-JSON. We switchedOllamaProviderto continuous NDJSON streaming, built a stack-based JSON auto-repair utility (repairJsonCandidate), and added a clean one-clickRetry Sendingbutton in the UI. - 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:4bandnomic-embed-textvia 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:4bas 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) 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, andclimate_location_knowledge), combining stateful multi-garden lifecycle persistence with 768-dimensional$vectorSearchretrieval 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. ๐ฑ



Top comments (0)