# AGRISENSE — Mukono Farm Operations
Smart farming operations dashboard for Mukono, Uganda. Weather, soil, alerts,
nutrition, recommendations, market prices, and a voice-style assistant for farmers.
AGRISENSE runs on **two interchangeable runtimes** against the same frontend:
1. **Cloudflare Worker (canonical)** — `src/index.js` + handlers in `src/api/*`
backed by **Cloudflare D1** (SQLite). This is the production path.
2. **Legacy Node.js server (local fallback)** — `server.js` serves the same
`/api/*` endpoints from an inline in-memory data object and static files
from `public/`. Useful when you can't run Wrangler/D1 locally.
Both serve the same single-page frontend in `public/` (Bootstrap 5 +
Material Symbols, vanilla JS SPA).
---
## Quick start — legacy Node (no install required)
```bash
node server.js
# or
npm start
```
Open
localhost. The legacy server needs no `npm install` and no
database — it returns hardcoded demo data.
## Quick start — Cloudflare Worker (canonical)
```bash
npm install # installs wrangler + @cloudflare/workers-types
npm run dev # wrangler dev — local Worker runtime
npm run deploy # wrangler deploy — production
```
### One-time D1 setup (required before first `npm run dev`/`deploy`)
1. Create the D1 database:
```bash
npx wrangler d1 create agrisense
```
Wrangler prints a `database_id`. Paste it into `wrangler.jsonc`, replacing
the `PLACEHOLDER_FILL_IN_AFTER_CREATE` value.
2. Apply the schema + seed data:
```bash
# Local (wrangler dev)
npm run db:migrate
# Remote (production D1)
npm run db:migrate:remote
```
These run `migrations/0001_init.sql` (11 tables) then
`migrations/0001_seed.sql` (40 INSERTs).
Until you complete D1 setup, the Worker's `/api/*` handlers will fail because
`env.DB` is unbound/empty. The legacy Node server (`npm start`) still works
without any of this.
---
## Architecture
```
agrisense/
├─ public/ Frontend SPA (served by both ru …