Garden Almanac is a full-stack project consisting of a React frontend (almanac-client) and a Node/Express backend (almanac-server) powered by MongoDB. It helps track plants, categories, events, and seasonal tips β with extras like Unsplash image integration and email-based authentication.
- almanac-client β React frontend
- almanac-server β Express + MongoDB backend
- almanac-shared β Shared constants and helpers (password rules, validation, etc.)
- π± JWT-based authentication (signup with email activation, login, forgot/reset password)
- π¦ Climate zone lookup (future: weather forecast proxy)
- π Event and plant management with categories
- π· Unsplash proxy endpoint (safe keys, cache-friendly)
- π§ Email delivery with Nodemailer (App Password or SMTP)
- π Validators, CORS, and logger utility for cleaner DX
- Frontend: React (Vite), Axios, TailwindCSS
- Backend: Node.js 18+, Express, MongoDB (Mongoose), JWT, Nodemailer
- Shared: npm package
@daidensacha/almanac-shared
Choose one configuration model:
- Option A β dotenv: local
.envfile (explicit, simple) - Option B β Phase: inject environment variables at runtime (no
.envfile)
- Node.js 18+
- MongoDB (local or Atlas)
- Client running at
http://localhost:5173
cd almanac-server
npm install
cp .env.example .env
# Important, edit and replace .env placeholders then continue with next step
npm run dev# .env - *** replace placeholders prior to running "npm run dev" ***
NODE_ENV=development
PORT=8000
LOG_LEVEL=debug
CLIENT_ORIGIN=http://localhost:5173
DATABASE_URL=mongodb+srv://<user>:<password>@<cluster>/<db>
JWT_SECRET=your_super_secret_key
JWT_ACCOUNT_ACTIVATION=activation_secret
JWT_RESET_PASSWORD=reset_secret
EMAIL_FROM=noreply.gardenalmanac@gmail.com
EMAIL_TO=noreply.gardenalmanac@gmail.com
GMAIL_PASSWORD=your_app_password
GOOGLE_CLIENT_ID=your_google_client_id
UNSPLASH_ACCESS_KEY=your_unsplash_key
β οΈ Never commit.envfiles..env.exampleis documentation only.
Phase injects environment variables at runtime (no local .env required).
This README assumes Phase is already installed and configured.
For setup and usage details, see: https://docs.phase.dev
Run the server:
phase run "npm run dev"Production-like start:
phase run "npm start"Environment variable names are identical to
.env.example.
npm run dev # development (nodemon, debug logging)
npm start # production-like startBase path: /api
POST /signupPOST /account-activationPOST /signinPUT /forgot-passwordPUT /reset-password
GET /plantsGET /categoriesGET /events- CRUD variants for each
GET /climate-zone/:lat/:lonGET /unsplash/photos?query=β¦
almanac-shared provides reusable constants and validation rules.
Exports:
PASSWORD_REGEXPASSWORD_MESSAGE
Usage:
// Client (ESM)
import { PASSWORD_REGEX, PASSWORD_MESSAGE } from '@daidensacha/almanac-shared';
// Server (CommonJS)
const { PASSWORD_REGEX } = require('@daidensacha/almanac-shared');- Current: Node 18 LTS
- Next: Node 20 LTS
- Verify Express & Mongoose compatibility
- Run
npm outdated - Upgrade incrementally (mongoose, nodemailer, jsonwebtoken)
- Express 4 β 5 (when stable)
- Audit middleware compatibility
- Unsplash keys must remain server-side
- JWTs are used for auth
- Email flows rely on Gmail App Password or SMTP
MIT Β© Daiden Sacha
