[CASE // SPROUT SQUAD]

Shared campus plant care

We had a bunch of plants around campus and people kept forgetting to water them. Classic engineer move: instead of a sticky note, I built an app.

The problem

Plants don't water themselves. We had pothos in the kitchen, a monstera by the window, chili plants on the sill — and no reliable system for who was responsible on any given week. Plants got thirsty. Someone would notice too late. Repeat.

Sprout Squad tracks every plant, rotates watering duty across the squad, and pings the assigned person on Discord when a plant goes overdue. Leaderboards and a people tab turned chores into something the team actually checked.

How it works

Sprout Squad mobile dashboard showing plant cards with watering schedules and rotation turns
App — rotations & schedules
Discord channel showing overdue plant watering alerts with assignee and location
Discord — overdue nudges

What I learned

This was my first time building something end-to-end, not a tutorial todo app or a cookbook, but a tool real people used every week.

Full-stack

React UI, Supabase Postgres, auth, and server logic wired together for the first time — from schema design to watering state machines.

Deployment

Shipped on Cloudflare Workers with a real URL the squad could bookmark. Learned env vars, migrations, and why staging matters.

Open source

Teammates contributed features and fixes. Code review, issues, and shared ownership made it feel like a real product, not a solo hack.

Security

Row-level access, auth boundaries, and making sure guests can browse but only members can water — small app, real stakes.

Database schema

Four core tables on Supabase Postgres — plants, users, events, and notifications.

plantsiduuidnametextimage_urltextwatering_interval_daysint4next_watering_datetimestamptzlast_watered_datetimestamptzassigned_user_iduuidlast_watered_by_user_iduuidmoisture_statusmoisture_statusnotestextoverdue_sincetimestamptzcreated_attimestamptzlocationtextlast_due_day_alert_datedatespeciestextwater_requirementwater_requirementcare_notestextplant_usersiduuidnametextemailtextrotation_orderint4avatar_colortextcreated_attimestamptzis_availablebooldiscord_user_idtextdiscord_display_nametextauth_user_iduuidwatering_eventsiduuidplant_iduuiduser_iduuidactionwatering_actionnotetextcreated_attimestamptzplant_notificationsiduuiduser_iduuidplant_iduuidtypenotification_typemessagetextreadboolcreated_attimestamptzauth.users.idexternal · Supabase Auth◆ REQUIRED · ◇ NULLABLE · ★ UNIQUE · PostgreSQL / Supabase

Stack

TanStack StartReact 19SupabasePostgreSQLCloudflareDiscord