Skip to main content
HB
Hiram BarskyDesigner and Developer
All work

Case Study

FarmFlow

An organisation with its own farm was taking plant requests by email and phone. This is the system that replaced the inbox, and it is still being built.

  • Internal Tools
  • Operations
  • AI-Assisted Product
  • Solo Build
Role
Designer & Developer
Status
Clickable build, backend next
Where a department lands after signing in. Play it and the walkthrough follows a request from Sarah in Events through to James on the farm team: new request, the queue, the ticket, the calendar, the catalogue, reports and the availability rules. Recorded off the live build with Playwright, so this is the app as it is today. Names and figures are the demo dataset.

01

A Farm That Ran on Email

An organisation with its own farm and landscaping team was taking requests from every other department by email and phone. Flowers for an event, herbs for the kitchen, a replacement for a dead shrub by the east entrance. Each one arrived in whatever form the sender felt like, and the farm team worked out the rest.

The line from the stakeholder that framed the whole thing was that the systemisation would be "great for efficiency and clarifying mutual expectations." Mutual is the word that matters. The farm did not know what departments were going to ask for, and departments did not know what the farm could grow or how long it took. Nobody was being difficult. There was just no shared place for either side to see the other.

So the job was a request system where both sides can see the same thing: what is available this week, what has been asked for, where it is in the process, and when it will arrive.

02

Twelve Screens Before a Line of Code

I started in July with twelve screens and a requirements document, and I wrote the document so that a coding agent could build from it one page at a time. Every page got its own build prompt: what it does, who can see it, every state it can be in, and what it must match pixel for pixel.

That sounds like process for its own sake. It was the opposite. Writing a prompt per page forced me to decide things a Figma file lets you leave vague, like what an admin sees when there are no requests yet, or what happens when a requester opens a ticket that has moved to a status they cannot act on.

The four screens here are from that July build. They are the version the stakeholder reacted to, which is the point of building a clickable one first.

Requester home, July. Four ways in and a top bar with five items. Compare it with the version at the top of this page.
New request, July. Five categories. There was no Fruits tab yet, and no department code or budget line on the form.
Admin dashboard, July. One admin role, with every privilege.
Admin calendar, July. Deliveries only. Reservations did not exist as an idea yet.

03

What the Feedback Added

The stakeholder came back with a list, and almost none of it was cosmetic. Fruits needed its own category. Honey and eggs were coming, so those had to be designed for even if they shipped behind a flag. Every request needed a department code and a budget line so it could be charged back. Email had to be a first-class way to be contacted, with phone as the backup rather than the other way round.

Two of the items were whole modules. Landscaping needed its own request type and its own admin, because a dead hedge is not a flower order. And departments wanted to reserve the farm itself, for tours, team events and harvest days, which meant the farm team needed a way to say which days and slots were open.

One item split a role in two. The farm lead wanted extra admins who could work the queue and manage the calendar day to day, but could not change when the farm was open. That became an Operations Admin, and it is the reason permissions in this app are individual privileges rather than role labels. Twelve screens became twenty-two.

July on the left, now on the right. The sidebar gained Landscaping and Reserve Farm, the cards gained a fifth, and the weekly availability banner stayed exactly where it was because nobody argued with it.

04

Four Roles, and Who Can Touch Availability

A requester sees their own department's requests and nothing else. The farm admin sees everything. The operations admin sees everything the farm admin does, and the one control they do not have is the farm's opening hours and reservation slots. The landscaping admin sees the landscaping catalogue and queue, and none of the farm's.

The interesting one is that missing control. It would have been easier to make Operations Admin a copy of Farm Admin with one checkbox unticked. Instead every admin capability is a named privilege, and a role is just a default set of them. That way the farm lead can grant or revoke one thing without inventing a new role, and when honey and eggs arrive and somebody needs a kitchen role, it is a row of toggles rather than a schema change.

The farm lead's first screen. Urgent items and anything waiting on a photo sit above everything else, because those are the two things that stall a delivery.
The one screen an operations admin can see but not change. Which days the farm is open, which slots can be booked, and whether a team member will be there.
Roles, departments, and the budget line each department charges to. The privilege toggles live behind each user row.
The landscaping admin's whole world. Their catalogue, their queue, and no way into the farm's.

05

The Request Is the Whole Product

Everything else exists to move a request from pending to delivered. A requester picks a category, then items from the catalogue with quantities and lead times already on them, then a location from their department's own list, a need-by date, how flexible that date is, and whether they want a photo before it leaves the farm.

That last one came from the farm side. Flowers for an event are the request most likely to disappoint, and the cheapest moment to find out is before the van leaves. So a request can ask for a photo, the farm team attaches one, and the requester confirms it from wherever they are. Every transition from pending through approved, in progress, photo confirmed and fulfilled is logged and shows up on the ticket as a timeline.

Needs Info is a status rather than an email. When the farm team has a question, it goes on the request, the requester answers on the request, and the answer is still there when someone looks at the ticket in three weeks.

A minute through the live build. Sarah from Events signs in, opens a new request, checks her queue and a ticket, looks at reserving the farm. Then James on the farm team: the request queue, the ticket from his side, the calendar, the catalogue, reports, and the availability rules only he can change. Recorded with Playwright against farmflow-app.netlify.app.
Fruits is the sixth tile, and the department code and budget line are filled from the department but editable per request. Both came from the feedback round.
The requester's view of a ticket. The timeline is the request_events log rendered as a story, and the farm contact is a real person with a preferred way to be reached.
The same request from the farm side. Approve, ask for more information, schedule, attach the confirmation photo, mark it fulfilled, or reject it, all from one column.
Deliveries and farm reservations on one calendar, in their own colours, because they compete for the same team on the same day.

06

Landscaping Is Simpler on Purpose

The brief for landscaping was a sentence: the farm has more options. A landscaping request is a new planting, a replacement, plants for an event, or maintenance, and the replacement flow is where the design work went.

When a plant dies, the person reporting it usually does not know what it was. So choosing the plant is optional. You can upload a photo of the damage, give a location or drop a pin on the property map, and describe it in your own words, and the landscaping team will go and look. The stakeholder's exact words were that landscaping can go to the location and see what is needed, but a description can help. The form is built around that sentence rather than around the catalogue.

Four ways into a landscaping request. Maintenance was added after the first round, because pruning a hedge is neither a new plant nor a dead one.
The plant picker says optional in the label. The description field is where the real information ends up.

07

Reserving the Farm Itself

Departments wanted the farm for things that were not plant orders: a team visit, a tour for new hires, a harvest afternoon, dinner in the farm's dining space. That is a different shape of request. It has a party size, a time slot, and a question about whether someone from the farm team needs to be there.

The constraint that made it work is that only slots the farm lead has opened can be booked. The reservation calendar is not a blank month you pick a day from; it is the availability manager's rules, rendered from the requester's side. If the farm is closed on Fridays, Friday is not a choice.

Open slots are the only slots. The toggle for a farm team member is what turns a booking into a staffing question on the admin side.
The queue from the farm side. Confirming a reservation that asked for a team member means assigning one, and it lands on the calendar next to that day's deliveries.

08

Built for a Phone Too

A requester checking whether Thursday's flowers were approved is not at a desk when they think to check. The requester side works at phone width: the sidebar folds behind a menu button, the availability banner keeps its place at the top, and the request cards stack one to a row.

  • Home. Same banner, same cards, one column.
  • New request. The category tiles wrap to two across.
  • My requests. Status counts first, then the list.
  • A ticket. The timeline reads top to bottom, the actions sit under it.

09

The Design System

A farm green for headings and the primary action, a sage for secondary text, cream for the surface, and Tailwind's stock status colours that only ever mean where a request is in its life. Everything sits on Tailwind's spacing scale so twenty-two hand-written pages stay on one grid.

The sage is the one that bit me. It measured 2.90:1 on white, on roughly eleven hundred pieces of secondary text at twelve to fourteen pixels, and it had looked fine to me for weeks. Fixing it took three passes to find a value that cleared 4.5:1 on white, on the cream, and on the darker banner at the same time. Chip text, white-on-fill buttons and the link colours failed in the same sweep and were darkened with it.

The catalogue the request form reads from. Lead times and stock live here, so a requester sees them before they ask.
Reports. Fulfilment and on-time rates by department, which is what the farm lead takes into the budget conversation.

10

The Build That Existed Nowhere

The part I got wrong was not on any screen. I had been shipping this by dragging a folder onto Netlify, fast, from wherever I was working, and at some point the working copy stopped being on any machine I owned. The live site was version twenty-nine. The most recent thing on disk was the twelve-screen July prototype.

I got it back by mirroring the deployed pages off Netlify into a repository, which means the project's history starts from the live build rather than from how it was written. It works, and every page since has gone through git. But it is a mistake that is specific to building this fast with AI: when producing a new version costs almost nothing, you stop treating any one of them as the thing you would be sorry to lose.

11

Where It Is

It is live at farmflow-app.netlify.app as a fully clickable build: twenty-two screens across four roles, every flow working, with demo data seeded in the browser. A twenty-two test Playwright suite covers sign-in for each role, the request lifecycle, approvals, reservations, search and the help centre, and it runs against the live site.

What it is not yet is connected to anything. The requirements document specifies the tables, the row-level security and the storage buckets. None of that is wired. That is the next phase, along with real sign-in, email notifications that honour each person's preferred contact method, and the honey and eggs categories that are designed and waiting behind a flag.

It is here as the front half of a product done properly: a real problem, a stakeholder whose feedback changed the structure and not just the copy, and a build you can hand to the people who will use it before a single database table exists.

Want something like this built?

I design and ship products end to end. Tell me what you're working on, or grab a time and we'll talk it through.

“Unmatched in his ability to translate the often vague ideas from clients into beautiful, simple-to-use products.”
Daanish · Business Delivery Partner, Tata Consultancy Services