All projects
PrototypeCoursework2025Full-Stack · MobileTeam Lead · 3-person team

FarmLink

A mobile agricultural marketplace backed by transactional APIs and PostgreSQL

A full-stack marketplace prototype connecting agricultural sellers and buyers through a Flutter client, RESTful Node.js services, PostgreSQL persistence, and managed product-media delivery.

At a glance

Outcome
Validated the complete marketplace path from role-aware onboarding and product media to catalog discovery and transaction-ready relational data.
Delivery
Prototype, 2025 · Coursework
Focus
Full-Stack, Mobile
Scope
15 core technologies
REST endpoints
48across 7 route modules
Schema tables
77 enums, 21 indexes, 7 triggers
Client screens
14~14k lines of Dart

What I built

The product decisions and engineering work that shaped the final result.

  1. Built a 48-endpoint REST API across seven route modules—users, farmers, buyers, products, cart, orders, and dashboard—with pagination, UUID, and payload validation applied as composable Express middleware rather than repeated inside handlers.

  2. Modelled the marketplace on a seven-table PostgreSQL schema whose seven enum types encode the domain's fixed vocabularies—three roles, ten product categories, a seven-state order lifecycle, six payment methods—so invalid states are rejected by the database instead of by application checks.

  3. Layered authorization as three separate JWT guards: role membership, resource ownership, and a farmer-product check that confirms the caller owns the product being modified, keeping the rule next to the route it protects.

  4. Made checkout validate the entire cart before writing anything, returning requested-versus-available detail for every unavailable line rather than failing on the first one, then decrementing stock, flipping products to out-of-stock at zero, clearing the cart, and rolling up buyer and farmer totals.

  5. Identified the checkout write path as non-transactional: the Supabase client exposes no transaction boundary, so a mid-sequence failure can decrement stock against a partially written order. The fix is to move the sequence into a Postgres function called as one RPC.

  6. Structured the Flutter client as MVVM over repositories across 14 screens and roughly 14k lines of Dart—six view models, four repositories, seven services, 14 typed GoRouter routes, and 12 dependencies wired through get_it.

  7. Uploaded product and profile images from the client straight to Cloudinary's REST API over multipart, behind a platform-neutral picked-image wrapper so web and native share a single upload path.

See it in action

Interface views and demonstrations from the working product.

Visual assets are not published for this project. The verified delivery and engineering scope are documented above.