02.4Major Project / Solo Developer5 sheets
Agriova: Offline Farm Ledger for Filipino Smallholders
Mobile farm ledger for smallholders in Cagayan de Oro that shows whether a season is earning money, with no signal needed. Farmers record expenses, harvests and sales in two or three fields, track produce before it spoils, and ask an assistant that answers from their own records. Android and iOS from one TypeScript codebase.

Season earnings, plots in progress and produce to sell
Sheet 1 of 5
Sheet 1 of 5. Season earnings, plots in progress and produce to sell
- Tech stack
- React Native
- Expo
- TypeScript
- expo-router
- SQLite
- Drizzle ORM
- Supabase
- PostgreSQL
- Deno Edge Functions
- Google Gemini
- Jest
- pgTAP
- Maestro
- EAS Build
- GitHub Actions
- Skills
- Offline-first architecture
- Sync engines
- Database security
- Mobile UI/UX
- Accessibility
- CI/CD
- Context
- Smallholders rarely know whether a season made or lost money, because records live in memory or loose notebooks. Pilot users average 57 years old, farm under weak signal on budget Android phones with 2 to 4 GB of RAM, and read Bisaya first. Every screen answers one of three validated questions: am I earning, will my harvest spoil, am I getting a fair price.
- Role
- Solo developer: product, design adaptation, mobile app, backend, sync engine, AI assistant, CI and release pipeline. Shipped as v1.0.0.
- Architecture
- Local-first. SQLite on the phone is the source of truth, so screens never wait on the network. A custom outbox engine pushes rows parents-first and pulls by server timestamp, with last-write-wins because each farm has one owner. Only sign-in, the assistant and account deletion need a connection.
- Money
- Amounts are integer centavos and quantities integer thousandths, identical on SQLite and Postgres, so profit totals never drift. Conversions live in one units module at every input and display boundary.
- Assistant
- Heat, rain and spoilage warnings come from a rules engine on the phone and work offline. Chat runs Gemini behind a Supabase Edge Function: the key never ships in the app, the phone sends a farm summary with no name or email, and a security-definer function enforces a 20-question daily quota in one statement.
- Security
- Row-level security on every farmer table, plus composite foreign keys on (id, owner_id) so the database itself refuses links to another farmer’s plot. Account deletion runs server-side from the caller’s token and cascades through every table before the phone is wiped.
- Design
- Adapts a Figma prototype to the real user: 56 dp touch targets, Bisaya and English for every string, layouts checked at 320 to 412 dp and 1.3x font scale. About 25 primitives on colour, type and spacing tokens; iOS uses native Liquid Glass tabs.
- Correctness
- 1,207 Jest tests against real SQLite, pgTAP tests for RLS and cascading deletes, and Maestro flows for onboarding and recording. Network calls carry a 20 s deadline with a warm-up health check after idle, tuned on the pilot hotspot. GitHub Actions runs every check on push; EAS Build and EAS Update ship releases.
