Plan crop rotations, planting schedules, and companion planting for garden beds and fields. Use when asked to manage a farm, garden, or plot layout; schedule what to plant and when; check companion planting relationships; track rotation history; or generate a printable planting schedule. Triggers include "crop rotation", "planting schedule", "companion planting", "garden bed", "what to plant", "frost dates", or any task involving seasonal crop planning.
Plan what to grow, where, and when. Tracks beds, crops, rotations, and generates a planting calendar from your frost dates.
Self-hosted. Run with Docker:
docker compose up -d
# App accessible at http://localhost:3000
Or run locally:
pnpm install
pnpm dev
# App accessible at http://localhost:3000
A bed represents a physical growing area: a raised bed, in-ground plot, or field strip. Each bed has dimensions (in feet or meters) and a grid layout where you assign crops to cells.
The crop database includes 30 common crops with growing data: days to maturity, spacing, sun requirements, water needs, whether to direct sow or transplant, and weeks before frost to start indoors.
The calendar computes all sow, transplant, and harvest dates from:
Each crop has defined friend and enemy relationships. The bed layout editor shows warnings when enemy crops are placed in adjacent cells.
The system tracks which plant family was grown in each bed each year. When the same family is planted again before the required rest period, a conflict is flagged.
All endpoints are at /api/. Requires session cookie if AUTH_PASSWORD is set.
| Method | Path | Description |
|---|---|---|
| GET | /api/beds | List all beds |
| POST | /api/beds | Create bed |
| GET | /api/beds/:id | Get bed with plantings |
| PATCH | /api/beds/:id/layout | Save layout JSON |
| Method | Path | Description |
|---|---|---|
| GET | /api/crops | List crops (supports ?search= and ?family=) |
| POST | /api/crops | Create crop |
| GET | /api/crops/:id/companions | Get companion relationships |
| Method | Path | Description |
|---|---|---|
| GET | /api/calendar | Planting calendar for active location |
| GET | /api/calendar?year=2025 | Specific year |
| Method | Path | Description |
|---|---|---|
| GET | /api/rotation | Rotation history per bed |
| GET | /api/rotation/conflicts | Detected conflicts |
| Variable | Description | Default |
|---|---|---|
| PORT | HTTP server port | 3000 |
| DATA_DIR | Directory for database and uploads | ./data |
| AUTH_PASSWORD | Optional password (empty = no auth) | (empty) |
| NODE_ENV | development or production | development |
| SESSION_SECRET | Session signing secret | (required in prod) |
| LOG_LEVEL | debug, info, warn, error | info |
Boolean env vars use 0 (false) and 1 (true).
1. Add beds: POST /api/beds {name: "North Bed", width_ft: 4, length_ft: 12}
2. Set frost dates: POST /api/frost-dates {location_name: "Springfield, IL", last_spring_frost: "04-15", first_fall_frost: "10-15", usda_zone: "6a"}
3. Activate location: POST /api/frost-dates/:id/activate
4. View calendar: GET /api/calendar?year=2025
5. Create planting: POST /api/plantings {bed_id: "...", crop_id: "...", year: 2025, season: "spring", planned_sow_date: "2025-04-15"}
6. Check conflicts: GET /api/rotation/conflicts
Ensure a frost date location is active: GET /api/frost-dates. At least one record must have is_active: 1.
The companion relationship must exist in both directions. Check GET /api/crops/:id/companions for each crop.
Confirm the plant family is spelled exactly as in the crop record. Conflicts are detected per family field value.