DEV Community

Cover image for How I built an AI-powered plant swap community app in a weekend
Soham
Soham

Posted on

How I built an AI-powered plant swap community app in a weekend

DEV Weekend Challenge: Community

This is a submission for the DEV Weekend Challenge: Community

The Community

Plant people are a weird and wonderful bunch.

I know this because I'm one of them. My balcony has more pots than chairs. My neighbors know me as "the guy with the jungle." And like pretty much every plant lover I know, I've spent an embarrassing amount of time in WhatsApp groups trying to swap cuttings.

You know how it goes. Someone posts "anyone want monstera cuttings?" and within 3 minutes there are 47 replies, half of them just "πŸ™‹", the thread is buried, nobody knows who got what, and the person who actually wanted the cutting lives 3 cities away.

That's the community I built this for β€” the balcony gardeners, the indoor jungle people, the "I propagated too many pothos again" crowd. People who want to share plants but have no good way to do it.

What I Built

BagichaLink β€” a plant swap platform where you can post plants you have or want, get AI to identify and diagnose them, find swap partners near you, and chat directly to arrange the swap.

"Bagicha" means garden in Hindi/Urdu. The name felt right.

Here's what it actually does:

You scan a plant. Point your camera at anything green. The AI (Groq's vision model) tells you what it is, how healthy it looks, gives you care tips based on your current local weather, and even drops a fun fact. It's weirdly satisfying even when you already know what plant it is.

You post it. Mark it as Available or Wanted. It goes into the feed for your city, nearby area, or the global feed.

AI finds you matches. Pick one of your plants and the AI scans through other posts and tells you who has something worth swapping with, why it's a good match, and gives it a match score.

You chat and swap. Real-time messaging, arrange the swap, mark it done.

There's also a live map showing posts from around the world, which is genuinely fun to look at β€” you can see someone in Tokyo just posted a succulent and someone in Lagos wants a fern.

Demo

🌐 Live: bagichalink.netlify.app

The backend runs on Render's free tier so the first load might take 20-30 seconds while it wakes up. After that it's fast. I added a friendly wake-up screen so it doesn't just look broken.

Here's what the flow looks like:

  1. Sign up (OTP sent to your email β€” no password needed if you don't want one)
  2. Set your location (GPS or search your city)
  3. Scan a plant or browse the feed
  4. Find a match, start a chat

Code

🌿 BagichaLink β€” Plant Swap Community

Swap plants with gardeners near you. AI identifies your plants, diagnoses health issues, and finds perfect swap matches. 100% free.

πŸ“Έ What is BagichaLink?

BagichaLink is a free, community-driven plant swap platform built for urban gardeners and plant lovers. Instead of cluttered WhatsApp groups or Facebook Marketplace chaos, BagichaLink gives you a clean, AI-powered experience to:

  • πŸ“· Scan any plant with your camera β€” AI identifies species, health, and care needs instantly
  • 🌍 Find swap partners near you or globally using smart AI matching
  • πŸ’¬ Chat in real-time with other gardeners to arrange swaps
  • πŸ—ΊοΈ Explore the Plant Map β€” see posts from around the world
  • πŸ“… Get a personalized care schedule based on your location and weather

✨ Features

πŸ”¬ AI Plant Intelligence

  • Instant plant identification β€” upload or photograph any plant and get species name, emoji, fun facts
  • Health diagnosis β€” AI…

How I Built It

Honestly? This started as a one-day thing and turned into a "okay one more feature" spiral that consumed the entire weekend.

The Stack

Frontend: React + TypeScript on Vite, styled with Tailwind. The design is intentionally warm and editorial β€” think botanical journal, not SaaS dashboard. Parchment backgrounds, terracotta buttons, DM Serif Display for headers. I wanted it to feel like something a plant person would actually like using, not just tolerate.

Backend: Node.js + Express + MongoDB. Socket.io for real-time β€” feed updates, chat messages, interest notifications all come through instantly.

AI: This was the fun part. I started with Google Gemini for plant vision analysis. It worked great until it... didn't (hit the free tier quota wall mid-weekend, classic). So I switched to Groq with llama-4-scout as the primary model, with Gemini as a fallback. Groq gives 14,400 free requests per day and it's fast β€” analysis comes back in under 2 seconds.

The weather integration (Open-Meteo, completely free, no API key) makes the care tips actually contextual. If it's 38Β°C and humid where you are, the tips are different than if you're in a cold dry climate. Small thing but it makes the AI output feel less generic.

Auth: Built email OTP from scratch using Nodemailer + Gmail App Passwords. Free, works, OTPs expire in 10 minutes via MongoDB TTL index. You can also use password if you prefer β€” both flows coexist.

Images: Cloudinary for storage. The tricky part here was that multer-storage-cloudinary streams straight to Cloudinary and discards the buffer, which meant Groq had nothing to analyze. Fixed by switching to multer.memoryStorage() β€” hold the buffer in RAM, send it to Groq as base64, then upload to Cloudinary. Obvious in retrospect, painful to debug.

Things That Went Wrong (aka the actual dev experience)

The MongoDB geo keys error. Spent 40 minutes on a MongoServerError: Can't extract geo keys error. Turned out MongoDB's 2dsphere index requires the coordinates array to be named exactly coordinates. I had named it coords. One word. Four letters. Forty minutes.

Express route ordering. Had /api/messages/:userId matching before /api/messages/conversations β€” so hitting the conversations endpoint was returning a "user not found" error because it was treating the string "conversations" as a user ID. Classic wildcard trap. Always put specific routes before /:param routes.

Socket.io and stale closures. The socket's connect handler was closing over user state which is null at mount time (user loads async from the API). Messages were saving with senderId: undefined. Fixed with a useRef that always holds the latest user value β€” the connect handler reads from the ref, not the stale closure.

Groq quota on vision. llama-4-scout is technically a vision model but I kept getting model-not-found errors until I got the exact model string right: meta-llama/llama-4-scout-17b-16e-instruct. Their docs aren't super clear on this.

What I'm Actually Proud Of

The bento grid feed layout β€” large card, two small cards, weather banner, repeat. It creates this nice visual rhythm without any CSS grid complexity.

The OTP digit input boxes that auto-focus as you type. Small thing but it feels really polished.

The AI fallback chain. Groq β†’ Gemini β†’ graceful fallback message. Users never see a broken state, just occasionally a "couldn't identify this one, try a clearer photo."

The match scoring system β€” AI reads your plant, reads 50 community posts, and gives you the top 3 with reasons. It's surprisingly good at finding complementary swaps (not just "you both have succulents" but "you have a drought-tolerant plant and they're in a dry climate").

What I'd Add With More Time

  • Push notifications (currently only in-app via socket)
  • A proper mobile app (the web app is mobile-optimized but PWA install would be nice)
  • Moderation tools for the community feed
  • More granular location β€” neighborhood-level matching, not just city
  • A "swap history" timeline so you can see all the plants that have moved through your hands

If you're a plant person, try it. Post something. See if anyone near you wants to swap.

And if you have a monstera cutting you're trying to get rid of β€” I'm probably interested.

Top comments (0)