I love brewing coffee. It is so many disciplines — cuisine, art, science, therapy — rolled into a 14 minute daily routine. I love the innovation happening in the coffee industry, from crazy but wonderful drinks like espresso tonic to new processes like anaerobic fermentation to newer exporters like the Nano Challa Cooperative.
Over the COVID-19 pandemic, I began to keep a journal of my daily V60 pourover, including notes on variables like coffee origin, grind size, and pour time. It was extremely helpful and pushed my technique drastically. Still, keeping a handwritten journal for a 14-minute routine was tedious — in most cases, my grind or coffee did not change, but for the sake of clarity, I wanted to include all these variables in every journal entry.
Recently, I began following James Hoffmann's channel. Three of his videos particularly inspired me:
- The Ultimate V60 Technique. I found this video at the passionate recommendation of a barista from Mudhouse Coffee Roasters. This got me thinking more about filter coffee as a technique in of itself.
- The Ultimate Hand Grinder Showdown. I never expected a GitHub repo to show up on a YouTube video. This coffee-related GitHub project by Jonathan Gangé analyzes an image of coffee grinds to determine particle size distribution.
- The World's Largest Coffee Tasting — Live! What an idea — a worldwide, remote tasting! I was again struck by the innovation happening in the world of coffee and its intersection with technology. Here I was introduced to the coffee tasting guide from Prufrock Training and Consulting.
I was inspired to combine both the journal and tasting aspects into a CLI (command line interface) that could generate JSON entries with static validation in Visual Studio Code.
This project requires:
- Fork or clone the repo.
git clone git@github.com:manuscriptmastr/kafi.git
cd kafi
-
Create a
.env
file using.env.example
for reference. -
Setup the
kafi
CLI.
# Install NPM dependencies
npm install
# Add kafi command
npm link
- Create a new journal entry.
# Create a new journal entry with sane defaults
# Use the --no-open flag to prevent VS Code from opening entry
kafi journal <cupping|hybrid|pourover>
- Brew your coffee, then jot out your reactions to things like:
- What does the smell remind you of?
- What does that fruity note remind you of?
- Do you like what you're tasting? What part of it do you like or dislike?
- How interesting is the overall flavor? Does it change, or is it rather one-dimensional?
- How does the coffee feel?
- How does your mouth feel during and after a sip?
- Use the Coffee Compass to create an action step. For instance, a coffee with a soupy body and a lack of tasting notes suggests an over-extracted brew, so next time you would make your grind coarser or decrease the overall brew time.
# Create and open a new journal entry
kafi journal <cupping|hybrid|pourover>
$ kafi stats pourover --coffee.origin.producer Sumatra
┌─────────┬──────────────┬─────────────────────────┬───────────────────────────┬──────────────┬───────────────────┬────────┬───────┐
│ (index) │ date │ coffee.roaster │ coffee.origin.region │ coffee.grind │ water.temperature │ time │ score │
├─────────┼──────────────┼─────────────────────────┼───────────────────────────┼──────────────┼───────────────────┼────────┼───────┤
│ 0 │ '05/19/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '212ºF' │ '2:49' │ 5 │
│ 1 │ '05/20/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 23 │ '212ºF' │ '2:44' │ 4 │
│ 2 │ '05/21/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '212ºF' │ '2:36' │ 7 │
│ 3 │ '05/22/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '212ºF' │ '2:41' │ 7 │
│ 4 │ '05/23/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 23 │ '210ºF' │ '2:50' │ 6 │
│ 5 │ '05/24/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '211ºF' │ '2:44' │ 7 │
│ 6 │ '05/25/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '212ºF' │ '2:33' │ 6 │
│ 7 │ '05/26/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24.5 │ '212ºF' │ '2:43' │ 7 │
│ 8 │ '05/27/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24.5 │ '212ºF' │ '2:34' │ 8 │
│ 9 │ '05/28/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '210ºF' │ '2:48' │ 9 │
│ 10 │ '05/29/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '210ºF' │ '2:38' │ 8 │
│ 11 │ '05/31/2021' │ 'Madcap Coffee Company' │ 'Mount Kerinci Highlands' │ 24 │ '211ºF' │ '2:31' │ 6 │
└─────────┴──────────────┴─────────────────────────┴───────────────────────────┴──────────────┴───────────────────┴────────┴───────┘
# Basic use
kafi stats <cupping|hybrid|pourover>
# Limit entries (defaults to last 30)
kafi stats pourover --limit 10
# Display specific fields (defaults to coffee.roaster, coffee.origin.country, coffee.grind, score)
kafi stats pourover --fields coffee.origin.region coffee.grind time
# Sort by fields (defaults to date)
kafi stats pourover --sort coffee.roaster score coffee.grind
# Filter results by properties
kafi stats pourover --equipment.grinder="Baratza Encore" --coffee.grind=23
# Merge entries on property (overrides --sort)
kafi stats pourover --merge coffee.grind --fields score
kafi export <from> <to> [template]
# Basic use
kafi export ./entries/01-03-2021.json ~/Desktop/entries/01-03-2021.json
# With template transform
kafi export ./entries/01-03-2021.json ~/Desktop/entries/01-03-2021.md --template ~/Desktop/my-template.md
# With date tokens. Be sure to escape spaces!
# See https://day.js.org/docs/en/display/format for accepted formats
kafi export ./entries/01-03-2021.json ~/Desktop/entries/{YYYY}/{MMMM}/{dddd},\ {MMM}\ {D},\ {YYYY}.md --template ~/Desktop/my-template.md
# Writes exported file to ~/Desktop/entries/2021/January/Sunday,\ Jan 3,\ 2021.md
~/Desktop/my-template.md
:
# {date}
## Coffee
- Producer: {coffee.origin.producer}
- Location: {coffee.origin.region}, {coffee.origin.country}
## Settings
- Grind: {coffee.grind} ({equipment.grinder})
- Temperature: {water.temperature}
## Results
- **Overall score: {score}/10**
- Acidity: {acidity.quality}/5
- Sweetness: {sweetness.quality}/5
- Body: {body.quality}/5
- Finish: {finish.quality}/5
- **Drawdown time: {time}**
~/Desktop/01-03-2021.md
:
# 01/03/2021
## Coffee
- Producer: Hernan Giron
- Location: San Vicente, Honduras
## Settings
- Grind: 24 (Comandante C40 MK3)
- Temperature: 208ºF
## Results
- **Overall score: 9/10**
- Acidity: 4/5
- Sweetness: 4/5
- Body: 5/5
- Finish: 5/5
- **Drawdown time: 3:38**
To build your own journal schema:
- Create a new JSON Schema file at
{rootDir}/src/schema/{method}.json
. Common subschemas such ascoffee.json
andwater.json
are provided. - Run the
build-schema
command:
# Example: npm run build-schema --type=espresso --release=1.1
npm run build-schema --type={method} --release={version}