derekc 84e7b13575 Add last login tracking, batch date auto-fill, and bug fixes
- Track last_login_at on User model, updated on every successful login
- Show last login date in admin panel user table
- Fix admin/garden date display (datetime strings already contain T separator)
- Fix My Garden Internal Server Error (MySQL does not support NULLS LAST syntax)
- Fix Log Batch infinite loop when user has zero varieties
- Auto-fill batch dates from today when creating a new batch, calculated
  from selected variety's week offsets (germination, greenhouse, garden)
- Update README with new features and batch date auto-fill formula table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 00:48:04 -07:00

Sproutly 🌱

A self-hosted plant growth tracking web app designed to help home gardeners manage their seed starting schedules, growing cycles, and garden transitions — all anchored to their local last frost date.

Overview

Sproutly takes the guesswork out of seed starting. Enter your plant varieties once with their frost-relative timing (e.g. "start 8 weeks before last frost"), set your last frost date, and Sproutly calculates exactly when to start seeds, move to the greenhouse, and transplant to the garden. A daily push notification via ntfy keeps you on track without having to check the app.

Features

  • Multi-user — each user has their own account with fully isolated data
  • Admin panel — manage all user accounts: view content, reset passwords, disable, or delete; shows each user's join date and last login
  • Dashboard — at-a-glance view of overdue, today's, and upcoming tasks with a full year planting timeline
  • Seed Library — manage plant varieties with frost-relative timing, germination days, sun/water requirements
  • Garden Tracker — log growing batches and track status from plannedgerminatingseedlingpotted uphardening offgardenharvested
  • Smart date auto-fill — when logging a new batch, sow date defaults to today and all subsequent dates (germination, greenhouse, transplant) are calculated automatically from the selected variety's timing
  • Year Timeline — visual calendar showing when each variety's stages fall across the year
  • Ntfy Notifications — per-user daily summary push notifications to your phone, configurable time, topic, and authentication
  • Settings — set your last frost date, fall frost date, location, timezone, and notification preferences

Stack

Layer Technology
Frontend Nginx (static HTML/CSS/JS SPA)
Backend FastAPI (Python)
Database MySQL 8.0
Auth JWT (python-jose + bcrypt)
Notifications Ntfy
Runtime Docker Compose

Getting Started

Prerequisites

  • Docker and Docker Compose

Run

git clone https://git.chns.tech/CooperandGoodman/sproutly.git
cd sproutly
cp .env.example .env   # set a strong SECRET_KEY and DB credentials
docker compose up --build -d

Access the app at http://localhost:8053 — create an account to get started.

First Steps

  1. Register an account on the login screen
  2. Go to Settings and enter your last frost date — this anchors the planting timeline and dashboard calculations
  3. Optionally configure an ntfy topic for push notifications
  4. Add varieties to your Seed Library — each variety stores its frost-relative week offsets and germination days
  5. Head to My Garden and log a batch — dates auto-fill based on today and the selected variety's timing

Environment Variables

Copy .env.example to .env and fill in all values:

MYSQL_ROOT_PASSWORD=sproutly_root_secret
MYSQL_USER=sproutly
MYSQL_PASSWORD=sproutly_secret
SECRET_KEY=your-secret-key-change-this
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=change-this-password

SECRET_KEY is used to sign JWT tokens. Generate a secure value with:

python3 -c "import secrets; print(secrets.token_hex(32))"

ADMIN_EMAIL and ADMIN_PASSWORD define the super admin account. This account is created (or updated) automatically every time the backend starts — changing these values in .env and restarting is all that's needed to update the credentials.

Project Structure

sproutly/
├── docker-compose.yml
├── .env
├── mysql/
│   └── init.sql          # Schema (multi-user)
├── backend/              # FastAPI application
│   ├── main.py
│   ├── auth.py           # JWT + bcrypt utilities
│   ├── models.py
│   ├── schemas.py
│   ├── database.py
│   └── routers/
│       ├── auth.py       # /auth/register, /auth/login, /auth/me
│       ├── admin.py      # /admin/users — admin-only user management
│       ├── varieties.py
│       ├── batches.py
│       ├── dashboard.py
│       ├── settings.py
│       └── notifications.py
└── nginx/
    ├── nginx.conf
    └── html/             # Static frontend SPA
        ├── index.html
        ├── css/style.css
        └── js/app.js

API

The FastAPI backend is available at /api/ and includes automatic docs at http://localhost:8053/api/docs

All endpoints except /auth/register and /auth/login require a Authorization: Bearer <token> header.

Key endpoints:

  • POST /api/auth/register — create account
  • POST /api/auth/login — get JWT token
  • GET /api/auth/me — current user info
  • GET /api/dashboard/ — dashboard data, tasks, and timeline
  • GET/POST/PUT/DELETE /api/varieties/ — seed variety management
  • GET/POST/PUT/DELETE /api/batches/ — growing batch management
  • GET/PUT /api/settings/ — app settings
  • POST /api/notifications/test — send test ntfy notification
  • POST /api/notifications/daily — trigger daily summary
  • GET /api/notifications/log — recent notification history
  • GET /api/admin/users — list all users with stats (admin only)
  • GET /api/admin/users/{id}/varieties — view a user's seed library (admin only)
  • GET /api/admin/users/{id}/batches — view a user's batches (admin only)
  • POST /api/admin/users/{id}/reset-password — reset a user's password (admin only)
  • POST /api/admin/users/{id}/disable — toggle account disabled state (admin only)
  • DELETE /api/admin/users/{id} — delete a user and all their data (admin only)

Admin Panel

Log in with the ADMIN_EMAIL / ADMIN_PASSWORD credentials from your .env. Once logged in, an Admin link appears in the sidebar. From there you can:

  • View all registered users with join date, last login, variety count, and batch count
  • Browse any user's seed library and growing batches
  • Reset a user's password
  • Disable or re-enable an account
  • Permanently delete an account and all associated data

The admin account itself cannot be disabled or deleted through the panel.

Ntfy Authentication

For private ntfy servers or access-controlled topics, the Settings page supports three auth modes:

Mode When to use
None Public ntfy.sh topics
Username & Password ntfy server with basic auth enabled
API Key / Token ntfy account access token (generate in ntfy account settings)

Batch Date Auto-fill

When logging a new batch, Sproutly pre-fills all date fields based on the selected variety's timing offsets, using today as the sow date:

Field Calculation
Sow date Today
Germination date Sow date + days_to_germinate
Greenhouse / pot-up date Sow date + (weeks_to_start weeks_to_greenhouse) × 7
Garden transplant date Sow date + (weeks_to_start + weeks_to_garden) × 7

All dates remain fully editable. Fields are left blank if the variety is missing the relevant timing value.

Status

Core infrastructure is functional. UI design and feature set are evolving based on user feedback.

Description
A self-hosted plant growth tracking web app designed to help home gardeners manage their seed starting schedules, growing cycles, and garden transitions — all anchored to their local last frost date.
Readme 177 KiB
Languages
JavaScript 37.9%
Python 34.4%
CSS 16.3%
HTML 11.2%
Dockerfile 0.2%