RomansLab project · 2026 →

Plantbot

I built Plantbot because I kept watering my plants and forgetting to log it. Each pot now has an NFC sticker that opens a page where I can record a watering. The tracker keeps the history and sends reminders through Telegram, with different intervals for summer and winter.

Go SQLite NFC Telegram Self-hosted
Running · 2026 →
An NFC sticker pushed into the soil of a white ceramic plant pot, next to the base of a green houseplant
On this page 7 sections

Plantbot keeps track of when I water my plants. Each pot has an NFC sticker that opens a page for that plant. After watering, I tap the sticker with my phone, open the link, and press a button to save the entry. Telegram sends a confirmation and a morning reminder when something is due.

The NFC stickers I use are listed on the Parts I use page, together with the affiliate disclosure.

Why I made it#

I had tried plant apps, but I kept forgetting to record waterings. Opening an app and finding the right plant was a small extra step that I often skipped. After a while, I couldn't tell whether an overdue reminder meant the plant needed water or I had just forgotten to log it.

I wanted to make that part easier. An NFC sticker gives each pot its own link, so I can go straight to the right plant without searching through a list.

I also considered soil moisture sensors, but that would mean adding hardware to every pot and dealing with power, calibration, and corrosion. For this version, I wanted to see how useful a watering log could be on its own.

How the NFC stickers work#

Each sticker stores a web address, something like this:

https://plants.example.com/t/monstera-thai?k=fd5df090b996403a

The phone reads the tag and offers to open the link. The page shows the plant's name and a button to record a watering. Plantbot runs on the server, using Go and SQLite; the sticker only needs to hold the URL.

NFC sticker in the pot
        |
        v
Phone opens the plant's page
        |
        v
Press the watering button
        |
        v
Plantbot saves the entry
        |
        v
Telegram confirmation

The schedule and watering history stay on the server. I can change the intervals or update the page without rewriting the sticker.

The k parameter is a key for that particular plant. The server derives it from the plant's identifier and a master secret, then checks it when the link is used. Someone with the link can record a watering for that plant, but the link does not give them access to the others.

The phone needs to support reading NFC tags. On phones with background tag reading, tapping the sticker brings up a notification without a separate NFC app. Some older phones need an app open to read the tag.

Recording a watering#

My first version recorded a watering as soon as the link opened. It saved a button press, but it also meant that any request to that address could change the log.

That is a problem with link previews. A phone, messaging app, or security scanner can fetch a page before anyone opens it. With the original approach, that request would count as a watering.

The current version separates opening the page from saving an entry. Loading the link shows the plant; pressing the button records the watering. There is one more tap, but previews can now open the page without changing anything.

I also added a ten-minute duplicate check. Repeated watering submissions for the same plant within that window count as one event. Reading the sticker again only reopens the page, and accidentally submitting the watering again does not add another entry.

The entry is saved before Plantbot sends the Telegram confirmation. If Telegram is unavailable, the watering is still in the log even though the message does not arrive.

Adjusting the intervals for the seasons#

I live in Finland, where the amount of daylight changes a lot between summer and winter. Keeping the same watering interval all year has led me to overwater plants in winter.

Each plant therefore has a summer interval and a winter interval. For example:

Plant Summer interval Winter interval
Thai Constellation 7 days 21 days
Snake plant 18 days 45 days
Basil 2 days 2 days

May through August uses the summer interval, and November through February uses the winter interval. The months in between use values between the two. Setting both intervals to the same number keeps a plant on one schedule throughout the year.

The calculation uses the month of the last watering. A plant watered on 30 August keeps the August interval for that watering, even when September starts. This avoids changing its next reminder just because the month has changed.

These intervals are starting points that I can adjust. The reminder tells me when to check a plant; I still need to decide whether it actually needs water.

Working out the next watering date#

Plantbot calculates the next watering date from the last recorded watering and the seasonal interval. It does not store a separate due date that has to be updated whenever the history changes.

That makes corrections straightforward. If I delete an accidental entry, the calculation uses the previous watering again. The history and the next reminder come from the same data.

Telegram reminders#

Each morning, Plantbot checks which plants are due and sends a message like this:

🌱 Watering — Sun 6 Sep

⚠️ Thai Constellation — 3 days overdue
💧 Dracaena cutting — due today

[💧 Thai Constellation] [⏰ +2d]
[💧 Dracaena cutting]   [⏰ +2d]

The buttons let me record a watering directly from Telegram or postpone a reminder by two days. Recording it there has the same effect as using the page from the NFC sticker: the watering is saved and the plant comes off the due list.

If nothing is due, Plantbot sends nothing. I only want a message when there is something to check.

The service also stores the date of the last morning message so it can check whether one has already been sent after a restart or deployment.

What I want to improve#

Plantbot records watering history, but it has no way to measure the soil or know how the plant is doing. A complete log is useful, but it still depends on me choosing sensible intervals and checking the plants.

Each plant has a chart comparing the actual gaps between waterings with its configured schedule. Mine already differ, so I want to use that history to adjust the intervals as I go, especially through winter.

The current version is for my own plants, with no user accounts or sharing. Soil moisture sensing is something I may try later. For now, I want to spend more time using the tracker and see how well the reminders fit the plants over a full year.