Field Kitchen

Client

Independent Study

Category

Interaction + Interface Study

Year

2026

Field Kitchen ingredient interface
Field Kitchen ingredient interface

Overview

Field Kitchen is a self-directed interface study about food as an information system. I wanted to see what happens when ingredients are organized by season, place, preparation, nutrition and pairing rather than mainly through recipes.

The Pacific Northwest edition uses a small regional ingredient set to explore those relationships through several different views.

Role & Scope

I designed the product structure, interaction model, visual system and working prototype.

The main challenge was giving different kinds of food data their own useful form without making the experience feel like a conventional database or dashboard.

Interaction Model

Users browse regional ingredients, compare seasonal windows, explore sourcing information, and move through pairing relationships using spatial fields and filtering rather than linear recipe lists.

What I Built

The prototype includes an Ingredient Library, Dataset Index, Pairing Field, Seasonal Map, Nutrient View and ingredient detail states.

Each view answers a different question: what ingredients are available, how they relate to a place or season, what preparation methods connect them, and how their nutritional relationships can be explored spatially.

Tools

Figma, AI-assisted prototyping.

Implementation

React · TypeScript · Motion · Vite · Tailwind · Interactive Data Visualization

I built Field Kitchen as a working interactive prototype rather than a fixed set of screens. Different views handle different kinds of relationships: the library supports browsing, the Pairing Field connects ingredients through preparation, the Seasonal Map turns harvest timing into a visual timeline, and Nutrient View treats nutritional relationships spatially.

The prototype was also a way to test how far the interface could stay quiet and editorial while still supporting fairly dense information.

src/app/views/PairingField.tsx

function getPairingStrength(
  selected: Ingredient,
  other: Ingredient
): PairingStrength {
  if (selected.id === other.id) return null

  const selectedListsOther = selected.pairings.some(
    p => nameMatch(other.name, p)
  )

  const otherListsSelected = other.pairings.some(
    p => nameMatch(selected.name, p)
  )

  const sharedPreps = selected.preparations.filter(
    p => other.preparations.includes(p)
  ).length

  if (selectedListsOther && otherListsSelected) {
    return sharedPreps >= 2 ? "strong" : "medium"
  }

  if (selectedListsOther || otherListsSelected) {
    return "medium"
  }

  if (sharedPreps >= 2) {
    return "experimental"
  }

  return null
}
function getPairingStrength(
  selected: Ingredient,
  other: Ingredient
): PairingStrength {
  if (selected.id === other.id) return null

  const selectedListsOther = selected.pairings.some(
    p => nameMatch(other.name, p)
  )

  const otherListsSelected = other.pairings.some(
    p => nameMatch(selected.name, p)
  )

  const sharedPreps = selected.preparations.filter(
    p => other.preparations.includes(p)
  ).length

  if (selectedListsOther && otherListsSelected) {
    return sharedPreps >= 2 ? "strong" : "medium"
  }

  if (selectedListsOther || otherListsSelected) {
    return "medium"
  }

  if (sharedPreps >= 2) {
    return "experimental"
  }

  return null
}
function getPairingStrength(
  selected: Ingredient,
  other: Ingredient
): PairingStrength {
  if (selected.id === other.id) return null

  const selectedListsOther = selected.pairings.some(
    p => nameMatch(other.name, p)
  )

  const otherListsSelected = other.pairings.some(
    p => nameMatch(selected.name, p)
  )

  const sharedPreps = selected.preparations.filter(
    p => other.preparations.includes(p)
  ).length

  if (selectedListsOther && otherListsSelected) {
    return sharedPreps >= 2 ? "strong" : "medium"
  }

  if (selectedListsOther || otherListsSelected) {
    return "medium"
  }

  if (sharedPreps >= 2) {
    return "experimental"
  }

  return null
}

Project State

Field Kitchen is built as a set of connected interactive views rather than a collection of static screens. A shared ingredient dataset drives the library, regional filters, seasonal timelines, source relationships, preparation methods, nutrient layouts and pairing behavior.

I was especially interested in making the relationships themselves visible. In the Pairing Field, ingredient connections change according to explicit pairings and shared preparation methods, while the Nutrient View reorganizes ingredients spatially as the selected nutritional metric changes.

Motion is used mostly to make those transitions readable-moving between views, reshaping data, revealing relationships and giving the interface a slower, more exploratory quality.