This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
ThirstyLeaf is a tiny plant-watering reminder app. Add a plant, pick a date and time, and it tells you when it’s thirsty. It’s a nudge to look up from the screen, walk over to your plants, and actually touch some (potted) grass.
It’s for anyone who keeps killing houseplants because they forget, which includes me.
Quick dates: Today / Tomorrow / In 3 days / Next week chips set the date in one tap.
Repeats: daily through monthly. Marking a plant watered reschedules from now, so a late watering still gets a full interval.
Needs water: everything that’s due is collected in one place, and the count shows in the browser tab title so you can spot it from another tab.
Watered / +1 hour / +1 day: mark a plant done or snooze it. One-time reminders move to Done, where Undo brings them back.
No account, no backend: everything lives in your browser’s localStorage.
Demo
Code
Ayushjhawar8
/
ThirstyLeaf
Set a reminder to water any plant on any day and time. No account, no backend — reminders are saved in your browser's `localStorage`.
🪴 Plant Reminders
Set a reminder to water any plant on any day and time. No account, no backend —
reminders are saved in your browser's localStorage.
Run it
npm install
npm run dev
Then open the URL it prints (usually http://localhost:5173).
| Script | What it does |
|---|---|
npm run dev |
Start the dev server with hot reload |
npm run build |
Typecheck and build to dist/
|
npm run preview |
Serve the production build locally |
npm run lint |
Run oxlint |
How it works
- Add a reminder with a plant name, a date, a time, and an optional note Use the Today / Tomorrow / In 3 days / Next week chips to set the date fast.
- Repeat turns it into a recurring reminder (daily through monthly). Marking it watered reschedules the next one from now, so a late watering still gets a full interval.
- Needs water collects everything that's due…
How I Built It
The app is a small React + TypeScript project built with Vite (npm run dev, npm run build, npm run lint with oxlint).
A few design choices:
Rules live in one place. lib/reminders.ts holds the repeat, water, snooze, and validation logic, so the UI components stay thin.
A ticking clock hook. useNow re-renders on an interval, so reminders turn due on their own without a refresh.
Persistence via a hook. useLocalStorage keeps state in the browser, so there’s no server to run or pay for.
Why Does Open Innovation Matter?
ThirstyLeaf's whole promise is that your data stays with you. Nothing leaves your browser. It would be odd to build that on a tool that sends my code and prompts to someone else’s servers.
Open tools made that consistent:
No lock-in and no gatekeeping. I didn’t need an API key, a billing account, or permission to start. A weekend idea stayed a weekend project.
I can see and control what I build with. Open models and tooling can be inspected, swapped, and run on my own terms. A closed API can change its pricing, behavior, or availability overnight.
The app is forkable by design. Because Rootine is open source and has no backend, anyone can take it and add what they need, like browser notifications, a PWA install, or sync, without asking me.
Small, useful, local-first tools are exactly what open innovation makes cheap to build and safe to share.

Top comments (0)