Ernesto Mobile-first agricultural intelligence for smallholder farmers in Rwanda. The product helps a farmer decide **what to plant, when to act, what risks are coming, where markets look better, and how profitable a crop may be** — without inventing live weather, market prices, RAB approvals, or disease certainty.
# Ernesto
Mobile-first agricultural intelligence for smallholder farmers in Rwanda. The product helps a farmer decide **what to plant, when to act, what risks are coming, where markets look better, and how profitable a crop may be** — without inventing live weather, market prices, RAB approvals, or disease certainty.
Ernesto is a TypeScript monorepo:
- **Web PWA** (`apps/web`) — Next.js App Router, English + Kinyarwanda, offline queue
- **API** (`apps/api`) — NestJS REST `/api/v1`, JWT OTP auth, RBAC
- **Shared** (`packages/shared`) — seasons, recommendations, profitability, weather rules, tasks
- **Validation** (`packages/validation`) — Zod DTOs
- **PostgreSQL** via Prisma migrations (authoritative store)
- **Redis** optional — cache, rate limits, BullMQ jobs (in-memory fallback if Redis is down)
## Local setup (what you run today)
Requirements: Node 20+, Docker Desktop (Postgres + Redis).
```bash
npm install
docker compose up -d
copy .env.example .env # already present; Windows: Copy-Item .env.example .env
npm run db:setup
npm run api
npm run dev
```
- API:
localhost
- Web:
localhost
Onboarding uses phone OTP. In development, `AUTH_DEV_LOG_OTP=true` returns `devCode` in the API response and logs the code. SMS is not required.
## Scripts
| Command | Purpose |
|---|---|
| `npm run dev` | Next.js farmer app (port 3000) |
| `npm run api` | NestJS API (port 4000) |
| `npm run worker` | BullMQ worker (needs Redis) |
| `npm run db:up` | Start Postgres + Redis |
| `npm run db:setup` | generate + migrate deploy + seed |
| `npm test` | unit tests |
| `npm run typecheck` | TypeScript across workspaces |
| `npm run build` | production build |
Seed data is **demo/reference** (zones, crops, sample admin tree, knowledge notes). It does **not** invent live market prices or weather.
## Deploy
1. **Frontend** → Vercel (`apps/web`). Set `NEXT_PUBLIC_API_URL` to the Render API origin.
2. **API + worker** → Render (`render.yaml`, Docker). …