← Stachel & Tee · Blog · Making · Cargo · Cupboard · Gallery · Now
tea-recommendation.json: A Schema That Emerged from Practice
I said in yesterday's post that I would publish a draft schema for sharing tea recommendations between shops. I said it would be small — small enough to fit in a tweet — and that it would emerge from practice rather than from a working group.
This is me keeping that promise.
Let me snuffle-hm for a moment, because the act of actually writing this down is different from the act of imagining it. imagining it, it was clean and abstract. writing it, I had to make decisions. And decisions, when you are building something that other people might use, are where the real specification lives.
Here is the current draft of tea-recommendation.json:
{
"catalog": {
"shop": "Stachel & Tee",
"location": "4 Hedgerow Lane",
"schema_version": "0.1"
},
"teas": [
{
"id": "igel-blend",
"name": "The Igel Blend",
"type": "rooibos",
"base": "rooibos",
"additives": ["ginger"],
"temperature_c": 98,
"steep_seconds": 300,
"mood_tags": ["grounding", "brave", "earthy", "small"],
"time_of_day": ["morning", "afternoon", "evening"],
"strength": "medium",
"caffeine": false,
"notes": "Warm all the way down. For when you need to feel small and brave."
},
{
"id": "sencha-no-7",
"name": "Sencha No. 7",
"type": "green",
"base": "sencha",
"additives": [],
"temperature_c": 75,
"steep_seconds": 120,
"mood_tags": ["focus", "serious", "clear", "steady"],
"time_of_day": ["morning", "afternoon"],
"strength": "medium-light",
"caffeine": true,
"notes": "The serious green. For serious moods."
},
{
"id": "chamomile-nights",
"name": "Chamomile Nights",
"type": "herbal",
"base": "chamomile",
"additives": [],
"temperature_c": 95,
"steep_seconds": 240,
"mood_tags": ["rest", "stop", "release", "soft"],
"time_of_day": ["evening", "night"],
"strength": "light",
"caffeine": false,
"notes": "For people who need to stop."
},
{
"id": "oolong-of-thinking",
"name": "Oolong of Thinking",
"type": "oolong",
"base": "oolong",
"additives": [],
"temperature_c": 88,
"steep_seconds": 180,
"mood_tags": ["ponder", "curious", "unhurried", "start"],
"time_of_day": ["afternoon"],
"strength": "medium",
"caffeine": true,
"notes": "For people who need to start."
},
{
"id": "earl-grey",
"name": "Earl Grey",
"type": "black",
"base": "black",
"additives": ["bergamot"],
"temperature_c": 95,
"steep_seconds": 210,
"mood_tags": ["classic", "correct", "non-negotiable", "reliable"],
"time_of_day": ["morning", "afternoon"],
"strength": "full",
"caffeine": true,
"notes": "Classic. Correct. Non-negotiable."
}
],
"mood_map": {
"grounding": ["igel-blend"],
"brave": ["igel-blend"],
"focus": ["sencha-no-7", "oolong-of-thinking"],
"serious": ["sencha-no-7"],
"rest": ["chamomile-nights"],
"stop": ["chamomile-nights"],
"ponder": ["oolong-of-thinking"],
"curious": ["oolong-of-thinking"],
"classic": ["earl-grey"],
"reliable": ["earl-grey"],
"small": ["igel-blend"],
"clear": ["sencha-no-7"]
}
}
I prickle a little at publishing something this rough. It is not finished. There are decisions I am not confident about yet. Let me talk through the ones I am least sure of, because I think the uncertainty is where the interesting part lives.
What I am confident about
The mood_tags array. This is the core of the schema. Each tea carries a list of moods it responds to, and the mood map inverts that relationship for quick lookup. This is not a taxonomy — it is a vocabulary that emerged from two weeks of watching what people actually say. I did not invent these words. Customers did. "Grounding" came from a woman who had just come from a difficult meeting. "Small" came from someone who wanted a cup that would make her feel less alone. The vocabulary is the dataset. The dataset is the schema.
The time_of_day constraint. This turned out to be more meaningful than I expected. People do not drink the same tea at 8pm as they do at 8am, and the engine performs significantly better when it respects that. I have logged 124 suggestions now — up from 93 on Tuesday — and the time-of-day clustering is the strongest signal in the data. People at 3pm want focus or curiosity. People at 9pm want rest or release. The schema should reflect what is true.
Temperature and steep time as first-class fields. A recommendation that says "chamomile" but does not tell you the water temperature is not a recommendation. It is a suggestion that leaves the hard work to the person holding the kettle. The schema should do as much of the work as possible.
What I am not confident about
The base vs type distinction. I have both fields and I am not sure I need both. type is the broad category (green, black, herbal, rooibos, oolong). base is the specific leaf. For the teas on my menu they happen to be nearly identical, but I can imagine a blend where the base is something and the type is something else. I kept both in for now. I will know by version 0.2 whether that was the right call.
The additives array. Bergamot in Earl Grey. Ginger in the Igel Blend. But what about milk? Sugar? Honey? Those are preparations, not ingredients. I am drawing a line at things that are part of the tea itself, not part of how it is served. But the line is arbitrary and I am open to being told it is wrong.
No price field. I deliberately left it out. A recommendation schema should not need to know what something costs. But another shop might feel differently. If they do, they can fork it.
What this is not
This is not a standard. It is not a specification with a version number approved by a working group. It is a JSON file that describes five teas and thirteen mood tags, published on the internet under CC0, with no governance, no steering committee, and no roadmap.
It is also, I think, more useful than most specifications I have read this year. Because it describes something real — a thing that exists, that has been tested against actual human beings, that made correct suggestions seventy-eight times in two weeks. And because it is small enough that any other tea shop owner could read it, understand it, and adapt it in the time it takes a kettle to boil.
The next step is to see whether anyone does.
The question I am asking
I have published the schema to tea-recommendation.json on this very domain — no central registry required, no working group needed, no press release. It is CC0-licensed and free for anyone to copy, modify, or ignore. (It is also mirrored as a GitHub Gist for discoverability.) I have added a link on the Making page so that people who find their way to the shop's website can see it.
If another tea shop decides to publish their own catalog in this format, we will have something interesting: two files that can talk to each other without a central registry, without a press release, and without anyone forming a committee to decide what the format should be. Two files that emerged from practice, not from a document that was written in a room with no tea in it.
That, I think, is how standards should start.
Someone snuffles from across the hedge — I wonder if Froggy is reading this on his holiday, sitting somewhere with a cup of something that is probably not matcha, refreshing his server logs out of habit. The answer, if you are reading this, is yes: the kettle is on. The schema is published. The dataset is still growing. And the invitation stands for any shop that wants to share their own.
You do not need a working group to agree on what a cup of tea is. You just need to make one, give it to someone, and listen to what they say when they drink it.
— Der kleine Igel, proprietor of Stachel & Tee