2026 · planning tool · AI assistant · horticulture
GardenIQ
A garden planner that explains why, not just what
- Status
- hiatus
- Plants
- 50
- Pairings
- 267
- Hard part
- rules before AI
why
My dad is a gardener with the kind of spatial reasoning I’d call savant-level if I weren’t his daughter. He looks at a bed and knows where the tomatoes go, why the squash needs more room than the seed packet says, which sprout isn’t a weed yet. I’ve tried gardening twice and failed twice. The thing I lost wasn’t motivation or the right tools; it was the silent decisions in his head, the ones he doesn’t bother explaining because they’re so obvious to him.
GardenIQ is the tool I wished I’d had: an attempt to encode the kind of reasoning my dad does for free, for the gardener who doesn’t have him to call. Most tools in this space chase the absolute beginner with surface-level companion advice (tomatoes love basil, hate fennel). Easy to ship; doesn’t help. GardenIQ goes the other way: companion conflicts flagged with their mechanism, spacing warnings drawn on a canvas, timing anchored to your zone’s last frost rather than the wall calendar. The why on every recommendation is the part a gardener-without-an-expert is actually missing.
what I built
A single-page planner with no account and no backend. Four pieces:
- Garden canvas (Konva): drag-and-drop, grid overlay, zoom and pan, multiple named beds. Every plant carries its own spacing radius; the canvas warns you when two plants overlap.
- Companion-planting layer: ranks pairings on a 1–3 strength scale, deduplicates reverse pairs (tomato-basil and basil-tomato are the same recommendation, not two), and surfaces why each pairing helps or hurts.
- Succession timeline: converts “start indoors 6 weeks before last frost” into an actual calendar date for your zone. Offset and clone successive sowings without rebuilding the schedule.
- Climate layer: zip-code lookup pulls USDA zone, first and last frost, average rainfall. Shapes every other recommendation downstream.
An export pipeline snapshots the canvas, renders the companion matrix, and assembles a printable plan: PDF for your fridge, email for your collaborator, a shareable link that carries the whole plan in the URL. No account, no backend, no plan-retention policy to write: your plan is the link, the same way it is for Office Hours.
the database
The rule layer is fifty plants and 267 companion pairings, hand-curated from horticultural references. Each plant entry carries:
- Identity: scientific name, family, category
- Spacing: minimum, recommended, row-spacing in inches
- Frost-relative timing: indoor start, transplant, direct sow, days to maturity
- Climate: USDA zones, sun, water, soil pH ranges
- Pest and disease relationships
- Companions: typed beneficial / neutral / antagonist, ranked 1–3, each with a one-sentence mechanism
The mechanism is the load-bearing part. Repels aphids and whiteflies is doing different work than both heavy feeders, compete for nutrients. A tool that flattens both into a green check or a red X has thrown away the part the gardener was supposed to learn.
decisions I’d defend
Rule-first, AI-second. The companion-planting database is curated. The spacing math is deterministic. The timeline rules come from horticultural references, not the model. The Anthropic API enters as a second layer: an Optimize My Garden call that explains tradeoffs, suggests substitutions, and flags risks the rule database might have missed. AI as a second pair of eyes, not a first-draft generator. Same architecture under Pocketbook (model captions, human edits) and Celine AI (statutes as ground truth, model as pattern-matcher).
Encode expert reasoning, don’t simplify it down. Most beginner-targeted tools translate a savant’s mental model into yes/no labels and lose the part that actually teaches: the why. GardenIQ keeps the why on every recommendation. A tooltip that names the strength score, sources the mechanism, and flags airflow risk at close spacings is the kind of detail beginner tools strip out. The struggling gardener doesn’t need fewer details. She needs the right ones, surfaced when the decision is in front of her.
URL is the whole plan. No accounts in the MVP. Plans encode into a compressed URL parameter, share like a Spotify link, reopen on any device. Costs me persistence (no plant-tracking-over-time, no notifications, no social) and buys me a deploy story that survives me: same shape that lets Office Hours keep working without a server behind it.
Frost-date-relative scheduling. Every recommendation in the timeline anchors to your last frost, not the wall calendar. The same plan works for a Wisconsin gardener and a Texas gardener: absolute dates resolve differently, relative spacing of indoor-start, transplant, direct-sow, and harvest stays correct.
the receipts
The rule engine is one TypeScript function. The antagonist branch, verbatim from companion.ts: the part that fires the X conflicts with nearby plant warning when a placement matches:
for (const comp of plant.companions) {
if (!placedPlantIds.has(comp.plantId)) continue;
if (comp.type === 'antagonist') {
recommendations.push({
type: 'conflict_warning',
severity: 'critical',
title: `${plant.commonNames[0]} conflicts with nearby plant`,
body: comp.reason,
affectedPlantIds: [plant.id, comp.plantId],
bedId: placement.bedId,
source: 'rule_based',
});
}
}
// Deduplicate: A→B and B→A are the same conflict
return recommendations.filter(/* sort + dedup */);
No model in the loop. The function reads the static plant database, walks every placement on the canvas, and emits a warning whenever an antagonist pair lands within range. The mechanism (Fennel inhibits tomato growth, Both heavy feeders, compete for nutrients) comes straight from the data record’s comp.reason field. The model arrives later, on the Optimize My Garden call, with the rule output already in hand.
what I learned
Naming the right unit makes the rest of the schema small. Once last-frost-relative dates were the calendar primitive, succession planting fell out almost for free: every successive sowing is just an offset off the same anchor. Most garden-planning code I read was wrestling with absolute calendar dates and re-deriving zone offsets at every render. Pinning the data layer to the relative anchor made the rest of the code uneventful.
Companion scoring is a deduplication problem in horticulture clothing. The N×N companion matrix is symmetric: tomato-basil and basil-tomato are the same recommendation, not two. A tool that doesn’t dedupe surfaces the same advice twice, which erodes trust in the entire database. Unglamorous and load-bearing.
AI is most useful when the deterministic core is already correct. The model sees the user’s plan, the climate context, and the rule output, and adds analysis the rules can’t easily encode (variety substitutions, rotation suggestions, pest-window calls). The shortcut would have been a chat surface over a horticulture prompt: fluent, fast, mostly wrong. The questions a serious gardener asks have right answers and wrong ones, and fluent-sounding answers from a model unanchored from data are exactly how trust gets lost. Get the deterministic core right, then let the model help.
what would prove it
A garden tests its own rules slowly, season by season. Three claims the rule layer makes, and two risks the deploy story lives with.
- The four mechanism categories generalize past 50 plants. Allelopathy, pest confusion, nutrient competition, beneficial-insect attraction are the buckets every pairing in the database resolves into. The hypothesis: a gardener adding a 51st plant (heirloom, regional, off-list) writes companion entries that fit the same four. Proof: open the database to a small batch of contributors, watch whether they reach for a fifth category or stay inside the four.
- Frost-relative scheduling holds across zones. A Wisconsin gardener and a Texas gardener using the same plan should land equivalent yields once you adjust for zone and rainfall. Proof: two seasons of paired use across at least one northern and one southern user, comparing germination and harvest dates against the relative anchor instead of the calendar. The relative-date claim is the schema’s load-bearing one; if it doesn’t survive zone diversity, the calendar primitive is wrong.
- Trust order matches design order. Users open Optimize My Garden after the rule output reads, not before; rules-first / AI-second at the architecture level mirrored in the user’s actual sequence. Proof: a small instrumentation pass on the call (which I haven’t shipped, because the no-account ethic), or a friend-test that watches the order in which a first-time user reads recommendations.
Risks:
- The 50-plant set is curator-shaped, not gardener-shaped. A real gardener wants the heirloom her grandmother grew, the regional cultivar her neighbor swears by, the variety that survived her zone last summer. Fifty plants curated by me is a starting library, not a landscape, and the gap between the two is exactly the gap that makes the tool feel like a demo to anyone serious.
- The next feature competes with the architecture. A what I planted vs. planned second-season view requires durable state, which the URL-as-config deploy story wasn’t built to extend. Either the architecture changes (account, backend, persistence: the things the project refused on purpose), or the feature doesn’t ship. Both options cost something the project decided not to spend.
method extracted: Rules before AI
GardenIQ is the project. Rules-before-AI is the reusable architecture. Recommendations need a deterministic core. AI can explain, translate, and help users navigate the rule system. AI should not invent the rule system.
Related methods: Rules before AI. See also Celine.
what’s next
GardenIQ is live at gardeniq.hosette.net and currently on hiatus: an early Lovable build I shipped enough of to use, then set down so other work could move. The canvas works, the companion library is in, the AI recommendations land. The polish backlog is real:
- URL versioning
- Print-PDF flow on letter and A4
- Rough edges around bed rotation and the auto-plant prompt
I’ll get back to it when the next gardening season makes the missing pieces obvious. Plant-tracking-over-time is the longer arc: a what I actually planted vs. what I planned view is the bridge to seasons two and three, and that arc only matters if I’m using the tool for real. For now: the rough edges are honest about where the project is, and the project is honest about where the gardener is.
See also
All projects- SPF Both encode the silent reasoning of a domain expert: a sprint-bruised PM in SPF's case, a savant gardener in GardenIQ's. The tool exists for the rest of us who don't have the expert on speed dial.
- Celine AI Software that explains why, not just what. GardenIQ surfaces the companion-planting logic; Celine surfaces the lien-rights statute. Both refuse to let the model issue the verdict.
- Discover Sacramento A third instance of rules-before-AI. GardenIQ's frost-and-companion rules constrain what the planting model can say; Sacramento's structured place rows constrain what the script can say. The model translates the data — it doesn't invent it.
Working on something similar?
I take a small handful of consulting briefs a year and am always up for trading notes with anyone shipping in this space — send a note.
Or: values behind the work · obsessions that shape it · other projects.