FarmDirect: A Farm-to-Consumer Marketplace Prototype (Flutter + Express + Postgres)
What it is
FarmDirect is a farm-to-consumer marketplace prototype: farmers list produce, retailers browse and order, delivery partners pick up and fulfill — three distinct apps sharing one backend. The repository (github.com/Shivay00001/farmdirect) contains a Node.js/Express API (backend/), a cross-platform Flutter app with role-based experiences (mobile/), and a React admin dashboard (frontend-admin/), plus a Postgres schema, Docker packaging, and an unusually self-aware README that labels the project an "early prototype / MVP foundation" and lists its own production-readiness gaps.
It was verified directly from source: the schema, controllers, Flutter screens, and admin panel all exist as real code. This article describes what's actually there — strengths, prototype traits, and all.
The problem it solves
India's agricultural supply chain loses value at every middleman. Farmers get the smallest share of the retail price; retailers struggle with inconsistent supply and quality; delivery is coordinated over phone calls. The structural problems a marketplace has to solve:
- Discovery — retailers can't easily find what farmers have, when it's harvested, and at what grade.
- Trust — quality, identity, and payment assurance across strangers.
- Fulfillment — someone has to move produce from farm gate to shop, with status visible to everyone.
FarmDirect models all three sides explicitly: five user roles, a full order lifecycle, delivery tracking, and payment records — not just a buy/sell listing board.
Architecture
farmdirect/
├── backend/ # Express API (auth, products, orders, admin)
│ ├── config/ # db.js, initDb.js, supabase.js
│ ├── controllers/ # auth, product, order, admin
│ ├── middleware/ # auth, upload, validation
│ ├── routes/ # route segmentation per resource
│ ├── utils/ # OTP service, token utils
│ ├── schema.sql # Full Postgres schema
│ └── server.js
├── mobile/ # Flutter app (farmer / retailer / delivery)
│ └── lib/
│ ├── core/ # api_client, auth_provider, constants
│ ├── features/ # auth, farmer, retailer, delivery screens
│ └── models/
├── frontend-admin/ # React + Vite admin dashboard
│ └── src/ # App, Dashboard, Users, api.js
├── Dockerfile / .env.example / LICENSE
The data model — built for Indian agri-commerce
backend/schema.sql is the most complete artifact in the repo, and it's clearly designed for the Indian market rather than a generic template. The users table carries a role CHECK constraint:
role CHECK (role IN ('FARMER','RETAILER','DELIVERY','SUPPORT','ADMIN'))
Each role gets a profile table with domain-specific fields:
- Farmer profiles — state/district/village, Aadhaar number, farm size, crops (JSONB), FPO (farmer-producer-organisation) membership, bank account + IFSC, and a verification workflow (
PENDING/VERIFIED/REJECTEDwithverified_by). - Retailer profiles — shop name, GST number, geolocation, and business type (
KIRANA/RESTAURANT/HOTEL/WHOLESALE). - Delivery profiles — vehicle type (
BIKE/VAN/TRUCK), driving licence, live location, online status, delivery stats.
Products carry category (GRAINS/VEGETABLES/FRUITS/DAIRY/SPICES), quality grade (A/B/C), harvest date, organic flag, and images. Orders model the money honestly: total_amount, platform_commission, delivery_fee, net_amount_to_farmer — the three-way split is first-class. The order state machine runs PENDING → ACCEPTED → PICKED_UP → IN_TRANSIT → DELIVERED (with REJECTED/CANCELLED escapes), payment status is separate (PENDING/PAID/REFUNDED/FAILED), and payment methods include COD/ONLINE/CREDIT with Razorpay fields on the payments table. Support tickets and order tracking are their own tables.
The backend — Express with a security posture
backend/server.js wires up an Express API with a sensible middleware stack:
app.use(helmet({ crossOriginResourcePolicy: false }));
app.use(xss()); // XSS prevention
app.use(hpp()); // HTTP parameter pollution protection
app.use(limiter); // 100 requests / 10 min per IP
app.use(express.json({ limit: '10kb' }));
Routes are segmented per resource (/api/auth, /api/products, /api/orders, /api/admin), there's an OTP service (utils/otpService.js), auth middleware, upload middleware, and a Socket.io server for realtime updates. The controllers show real transactional thinking — orderController.js wraps order placement in BEGIN/COMMIT/ROLLBACK, decrements product quantity inside the transaction, and restricts order placement to retailers (403 'Only retailers'):
await client.query('BEGIN');
// ... insert orders, decrement inventory ...
await client.query('COMMIT');
// on error: ROLLBACK
Status changes also append to order_tracking, so the order's journey is auditable.
The mobile app — one codebase, three storefronts
The Flutter app routes users by role from the splash screen itself (mobile/lib/main.dart):
if (role == 'FARMER') → FarmerDashboard()
else if (role == 'RETAILER') → RetailerHome()
else if (role == 'DELIVERY') → DeliveryDashboard()
else → LoginScreen()
Each role gets its own feature folder with purpose-built screens: farmers get add_product_screen (listings with image upload), farmer_orders_screen; retailers get marketplace browsing and retailer_orders_screen; delivery partners get delivery_dashboard for job acceptance and status updates. The ApiClient is a singleton that injects the stored JWT (Authorization: Bearer) from SharedPreferences on every request and throws structured errors on non-2xx responses.
Authentication and the delivery loop
Auth is mobile-number based, matching how the target users actually operate. The login screen (features/auth/login_screen.dart) feeds into an AuthProvider (ChangeNotifier) that persists the token and user role in SharedPreferences, enabling the auto-login check on the splash screen. On the backend, authController.js and the OTP service (utils/otpService.js) handle verification, while authMiddleware.js protects the routes and tokenUtils.js manages token issuance. The delivery experience closes the operational loop: getAvailableDeliveryOrders in the order controller serves orders in READY_FOR_PICKUP / OUT_FOR_DELIVERY states to the delivery dashboard, and every status update appends a row to order_tracking — so the farmer, retailer, and delivery partner all see the same auditable journey. It's worth noting the order-number generation is still demo-grade random ('ORD-' + Math.floor(Math.random()*10000)), which would collide in production and needs replacing with a proper sequence.
The admin panel
frontend-admin/ is a React + Vite dashboard (Dashboard.jsx, Users.jsx, api.js) for platform oversight — monitoring users, roles, traffic, and transactions. The repo even includes a prebuilt dist/ bundle, suggesting the panel was deployed or demoed at some point.
Honest status — the prototype traits
The README says "early prototype / MVP foundation," and the code corroborates it. Things a reviewer should know:
- The order controller has SQLite-flavored comments ("In SQLite, FOR UPDATE is not supported") — the schema is Postgres, but some controller code paths were developed against a lighter DB. Verify against real migrations before production.
- Order numbers are placeholder random (
'ORD-' + Math.floor(Math.random()*10000)), and the API response masks them further (order_number: 'ORD-...'). Fine for a demo; not for commerce. - Build artifacts are committed:
mobile/.dart_tool/,mobile/build/,mobile/android/.gradle/are in the tree. The repo is ~44MB largely because of this. A.gitignorecleanup would cut it dramatically. - The Dockerfile is a stub, and there's no CI (no lint/test/build pipeline).The README's own roadmap lists exactly these gaps — tests, auth-flow verification, upload hardening, payment wiring, localization — which is honest.
- The advertised "AI demand prediction, price suggestions, crop-health checks" in the repo description do not appear as implemented features in the tree I verified. Treat them as roadmap, not shipped.
What's genuinely solid for a prototype: the domain model (India-specific fields, three-way money split, verification workflows), the transactional order controller, role-based access, the security middleware stack, and the three-role mobile architecture. The strongest single artifact is schema.sql itself — it reads like it was designed by someone who has thought about how a mandi actually settles money, not just how a CRUD app stores rows.
How to run it
git clone https://github.com/Shivay00001/farmdirect.git
cd farmdirect
# Backend (port 5000)
cd backend && npm install && npm start
# Mobile
cd mobile && flutter pub get && flutter run
# Admin panel
cd frontend-admin && npm install && npm run dev
You'll need Node.js, the Flutter SDK, and a database/auth setup (Supabase config stubs exist in backend/config/supabase.js; env vars are documented in .env.example). The README's configuration section lists every production variable to verify: DB URL, Supabase keys, JWT secret, CORS whitelist, upload storage.
Roadmap (from the project's own assessment)
The repo's roadmap is refreshingly specific: verify the schema and auth flows against real migrations, add automated tests for marketplace flows and role validation, add order lifecycle and payout logic, harden uploads and storage, add payment/invoice/escrow workflows, analytics and demand forecasting, localization and multi-language support, and a demo deployment environment. The commercial section also sketches monetization paths — SaaS subscriptions, transaction fees, white-label deployments for cooperatives, managed hosting — under a VisionQuantech Custom Commercial License (read it before commercial use; it's not MIT).
Why it matters
Agritech marketplaces fail on trust modeling, not on UI. FarmDirect's interesting parts are all in the trust layer: per-role verification workflows, quality grades, the three-way money split, auditable order tracking, and a security-conscious API. As a prototype it's exactly what it claims to be — a technical foundation with a real product shape. For builders working on rural commerce, the schema alone is a useful reference for how to model farmers, retailers, and delivery partners without flattening them into "users."
Source: github.com/Shivay00001/farmdirect · VisionQuantech Custom Commercial License
Frequently asked questions
What is FarmDirect?
An open-source farm-to-consumer marketplace prototype: a Node.js/Express API, a Flutter mobile app with separate farmer, retailer, and delivery experiences, and a React admin dashboard. It is licensed under the VisionQuantech Custom Commercial License.
What makes its data model India-specific?
Farmer profiles carry Aadhaar, FPO membership, and bank/IFSC fields with a verification workflow; retailer profiles carry GST numbers and business types (kirana, restaurant, hotel, wholesale); the payments table has Razorpay fields; and payment methods include COD, online, and credit.
Is it production-ready?
No — and its own README says so, labeling it an early prototype. Verified gaps: placeholder random order numbers, SQLite-flavored comments in the order controller, committed build artifacts inflating the repo to ~44MB, a stub Dockerfile, and no CI. The "AI demand prediction" in the repo description is roadmap, not shipped code.
How do I run it?
Clone the repo, run npm install and npm start in backend/ (port 5000), flutter pub get and flutter run in mobile/, and npm install with npm run dev in frontend-admin/. You need Node.js, the Flutter SDK, and a database/auth setup — Supabase config stubs and a .env.example are included.