Files
sproutly/README.md
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

170 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](https://ntfy.sh) 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 `planned``germinating``seedling``potted up``hardening off``garden``harvested`
- **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
```bash
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](https://ntfy.sh) 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:
```env
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:
```bash
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.