bloombase/README.md
Stephan Kerkman 35bf5eee70 docs: add README with setup, deployment, and data source research
Covers local dev, Docker deployment, env vars, data model, and
a summary of plant data sources investigated (Perenual, OpenFarm,
Trefle, Wikipedia, Google) including the commercial data opportunity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:26:44 +02:00

112 lines
4.1 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.

# PlantDB
A personal plant management web app built with Django 5, Bootstrap 5, and HTMX.
Track your plants, log pruning activity, and get care info auto-filled from the Perenual species database.
## Features
- **Species search** — search Perenual API by name; care data (watering, sunlight, pruning months) is auto-filled into the plant form and cached locally so the API is only called once per species
- **Plant list** — filterable by name, location, indoor/outdoor
- **Plant detail** — shows care info, pruning status, and pruning history
- **Pruning log** — log a pruning event with date and notes via HTMX partial update
- **Pruning calendar** — all plants grouped by urgency: overdue, due this month, due next month, later
- **Dashboard** — plant count, overdue pruning count, and attention list
## Data model
```
Species — cached from Perenual API (common_name, scientific_name, watering,
sunlight, pruning_months, api_image_url, perenual_id)
Plant — your actual plant (name, location, is_indoor, pruning_months,
photo, notes, species FK)
PruningLog — pruning events (plant FK, pruned_on, notes)
```
`Plant.pruning_months` is a JSON list of integers (112). It defaults to the species value but can be overridden per plant.
## Tech stack
| Layer | Library |
|---|---|
| Framework | Django 5.2 |
| Frontend | Bootstrap 5.3 + HTMX 1.9 |
| Image handling | Pillow |
| HTTP client | requests |
| Server | Gunicorn + Nginx |
| Database | SQLite |
## Local development
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py runserver
```
Set `PERENUAL_API_KEY` in your environment to enable species search (free tier: 100 requests/day).
Run tests:
```bash
pytest
```
## Deployment (Docker)
The production stack runs as two containers: `web` (Gunicorn) behind `nginx`.
```bash
# On the host — first time
cp .env.example .env # fill in SECRET_KEY, PERENUAL_API_KEY, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS
docker compose up -d --build
```
After code changes:
```bash
# Sync files from dev machine
rsync -av --exclude='*.pyc' --exclude='__pycache__' . dockerhost:/home/stephan/stacks/plantdb/
# Rebuild
ssh dockerhost "cd /home/stephan/stacks/plantdb && docker compose up -d --build web"
```
### Environment variables
| Variable | Required | Example |
|---|---|---|
| `SECRET_KEY` | yes | long random string |
| `DEBUG` | no | `False` |
| `ALLOWED_HOSTS` | yes | `localhost,127.0.0.1,dockerhost` |
| `CSRF_TRUSTED_ORIGINS` | yes (non-localhost) | `http://dockerhost:8083` |
| `PERENUAL_API_KEY` | no | `sk-...` |
`CSRF_TRUSTED_ORIGINS` is required when accessing the app on a non-standard port or hostname — Django 5 rejects POSTs without it.
### Volumes
| Volume | Purpose |
|---|---|
| `db` | SQLite database at `/app/data/db.sqlite3` |
| `media` | User-uploaded plant photos |
| `static` | Collected static files |
## Plant data sources — research notes
The app currently uses **Perenual** (free tier, 100 req/day) for species data. Other sources investigated:
| Source | Status | Verdict |
|---|---|---|
| **Perenual** | Active | Best structured care data (watering, sunlight, pruning months). Free tier sufficient for personal use; each species is cached after first lookup. |
| **OpenFarm** | Shut down April 2025 | Dead. GitHub repo is a Ruby/MongoDB app with no data dump. |
| **Trefle** | Active | Botanical taxonomy only — no care schedules. Not a replacement. |
| **Wikipedia API** | Active | Returns name, description, thumbnail. No structured care data. |
| **Google Knowledge Panel** | N/A | Has structured care data but scraping violates ToS and is technically brittle. |
### Future opportunity
Google's plant Knowledge Panels aggregate care data (watering frequency, sunlight, pruning) from sources like The Sill, Bloomscape, Gardenia.net, and others. A curated, structured plant care dataset — particularly one covering common garden plants in NW Europe — does not currently exist as a clean, accessible API. This could be a commercial opportunity: either licensing a dataset or building a plant care API as a product.