Skip to main content
JCR.DEV / DESIGN
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.

Agriova home screen on a phone, showing season earnings over a field photo, plot cards and a produce-to-sell countdown.

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

5 sheets
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.