Full‑stack demo that lets you create virtual hydroponic “pods”, attach photos, and track growth over time.
| Layer | Highlights |
|---|---|
| Backend | FastAPI 0.111, SQLite via SQLAlchemy 2, REST (+ OpenAPI docs), image upload with type/size validation (JPEG / PNG / WebP ≤ 5 MB), static file serving, CORS whitelisting |
| Frontend | Vite + React 18, functional components with hooks, modal & image slider, responsive CSS, hero section & grid view, form‑data POST via Axios |
| Dev DX | Hot‑reload (uvicorn --reload, vite dev), type‑safe env access when using TypeScript (env.d.ts), ready‑made requirements.txt |
plant‑pods/
├─ backend/
│ ├─ main.py # FastAPI application (this repo)
│ ├─ pods.db # SQLite database (auto‑generated)
│ ├─ uploads/ # Saved images 👍
│ └─ requirements.txt
└─ frontend/
├─ src/
│ ├─ App.(t)sx # Root page
│ ├─ components/ # Header, Footer, Modal, PodCard …
│ └─ styles/
└─ vite.config.ts
git clone https://github.com/<you>/plant‑pods.git && cd plant‑podscd backend
python -m venv venv && source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload --port 4000Open http://127.0.0.1:4000/docs for interactive Swagger UI.
cd ../frontend
npm install
npm run dev # default http://localhost:5173Front‑end expects VITE_API_BASE (defaults to http://localhost:4000). Create a .env if you need a different port / host.
| Method & Path | Body / Params | Response Sample |
|---|---|---|
GET /api/pods |
— | [ { id, name, images:[...] } ] |
POST /api/pods |
form‑data name, species? plantedAt? description? image? |
created pod JSON |
POST /api/pods/{id}/images |
form‑data image | { id, url } |
GET /uploads/{filename} |
— | raw file |
Note – uploads are validated to be ≤ 5 MB and of type JPEG, PNG, or WebP.
| Var | Default | Purpose |
|---|---|---|
DB_PATH |
backend/pods.db |
SQLite location |
UPLOAD_DIR |
backend/uploads |
Directory for images |
ALLOWED_ORIGINS |
http://localhost:5173,3000 |
CORS whitelist |
Use a .env file or export vars before launching uvicorn.
- Unique filename via
uuid4() - Size & MIME checked (
ALLOWED_IMAGE_TYPES+MAX_FILE_SIZE) - Served through FastAPI’s
StaticFilesmount (updatemain.pyas recommended in comments).
- Pydantic schemas – replace manual dicts with
response_model=…for type‑safe JSON. - Auth – add
fastapi-usersor JWT routes to protect endpoints. - Docker – multi‑stage build (
backend→ uvicorn,frontend→ nginx static).
- Fork & create a feature branch.
- Run
ruff/black(pre‑commit) before pushing. - Open a PR describing your change.
MIT © 2025 Selvy Labs