Pincode Garden: what to plant this week, from your pincode
Live demo: https://pincode-garden.onrender.com/
Repo: https://github.com/ishaan-jindal/pincode-garden (MIT)
The problem
I have killed every plant I ever touched. The advice online is always "zone 9b, last frost March" — useless when your pincode is 110016 and your garden is a balcony with three hours of sun.
So for Hacktoberfest Week 1 (Touch Grass) I built the smallest thing that answers one question: given my pincode, my minutes per week, my sun, and my experience, what should I sow this week?
You enter four fields, you get up to three crops with a sow-by date, one short tip, and the frost window it was grounded in. Then you are supposed to close the laptop and go sow something. The screen part takes twenty seconds. That is the point.
What it does
Input: pincode, minutes per week, sun (full / partial / shade), experience (new / some / green).
Output: three ranked crops, each with why it fits, a sow-by date, and a fit score — plus one tip line, the last/first frost for your prefix, weeks left in the window, and two flags: smart advice on/off, yield check on/off.
Example — 110016, 30 min, partial sun, new gardener — returns coriander, lettuce, marigold with a tip like "Sow coriander 3in apart; keep moist, harvest in about 35 days." Completing a planting logs a streak in a flat file. No accounts, no database, no keys.
The read-aloud button reads the tip plus the top pick, so you can listen once and put the phone away.
How open-source AI is at the core
Two open pieces do the actual work, both with the same honest pattern: try the real model, fall back to a deterministic stub, label which path ran.
Gemma 4 via Ollama writes the tip. The prompt is grounded in the top-ranked crops only, strict JSON, one line. Model and host come from GEMMA_MODEL (default gemma4:e2b) and OLLAMA_HOST. No cloud calls, no keys, no per-token bill.
TabPFN V2 (CPU) ranks the candidates. Features are tabular and small: sun match, frost-window fit, harvest fit, experience, month. The training table (data/history.csv, 32 rows) is reference outcomes encoded from planting guides, not fake telemetry. Fit happens once and is cached; any failure falls back to a weighted stdlib scorer over the same features.
Why open mattered here: the whole brain runs on-device or not at all. Nothing about your pincode or garden leaves your network. The stub path means the demo works with Wi-Fi off — Gemma makes tips warmer when home, TabPFN sharpens ranking when torch is around. On Render free the deployed demo runs the deterministic fallback by design, and the UI says so. Locally, uv sync --extra tabpfn plus ollama run gemma4:e2b enables both real paths with zero code changes.
Frost dates without an API
data/frost.csv is ten rows: pincode prefix to first/last frost (MM-DD), plus a fallback row for unknown prefixes. North prefixes get a real window; southern ones get year-round. All math is stdlib dates. No fetch, no keys, no outage mode.
Crops live in data/crops.csv (14 rows). Candidates are filtered by sun, difficulty, time budget (under 30 min/week keeps easy herbs/greens only), and whether the sow-by date is still inside the window. Unknown pincodes never crash; they get the fallback window.
Stack and shape
FastAPI plus stdlib. No ORM, no auth, no image uploads, no weather API, no geolocation. Streaks are a JSON file. Frontend is one 74-line HTML file, system font, no framework, speech synthesis for read-aloud. Tests are five offline pytest cases with stubs forced. Docker plus render.yaml on the free tier.
What I would add with more time
A second frost source with provenance per row, and a photo log for the streak instead of a counter. Neither fits a four-day window without adding a database I would have to maintain.
Top comments (0)