Tazzina

Reducing the waste and guesswork of dialing in coffee.

Download on the App Store

Role
Creator: design, engineering and operations
Team
Solo
When
Since January 2026

My favorite interactions

I like making products that feel like real physical objects. Tazzina is where I leaned into that the hardest.

Context

I started Tazzina after getting into espresso. Dialing in means adjusting grind size, dose, yield, time and temperature until a coffee tastes right. It took me two to five shots per bag, so 15% to 35% of a 250g bag was gone before the first good cup. I designed and built all of it myself: the SwiftUI app, backend, bag scanning, suggestions, website and an admin console.

shots to dial in a new bag
2–5
of coffee wasted per bag
36–90g
of a 250g bag gone before a good cup
15–35%

My system was grind size written on masking tape. That broke down once I had several beans in rotation.

Masking tape on coffee bag with grind size written on it

Why start from the bean

Notes and apps like Beanconqueror are spreadsheets with a UI. They know nothing about a bean or a grinder until you type it in. I wanted a journal that understands coffee, so Tazzina starts from the bean. Every bean is a public entry in a shared library, like wines on Vivino. You scan the bag or search for it and your brew attaches to that bean. When a bag runs out you archive the bean and its brew stays with it. Knowing the bean also lets Tazzina track freshness and suggest how to brew it.

Tazzina home screen listing current beans as cards with roast date, freshness, and saved brew Tazzina collections screen with stacked bean cards using coffee-bag artwork Tazzina camera screen scanning a coffee bag to identify the bean

Guided dial-in

The guided flow changes one variable at a time so beginners don't overcorrect. I tried a tasting compass first and dropped it because it assumes people can describe what's wrong with a cup. Tazzina asks with photos instead: sour is a lemon and bitter is chocolate. Every guided brew is also cleaner data for suggestions.

Tazzina guided dial-in step asking how the brew flowed, with photos of a pour-over running slow, steady, and fast Tazzina taste step showing sour, perfect, and bitter as a lemon, an orange, and chocolate Tazzina brew screen with plain-language sliders for grind, water, and temperature

Strategy pivot

Suggestions are what set Tazzina apart. If enough people save brews for a bean, Tazzina can say "start here" instead of everyone wasting the same shots. Grind size makes this hard. "Grind 6" means nothing without the grinder, so suggestions only draw from brews on the same one. Translating between grinders needs even more data and a new app doesn't have it.

So instead of leading with suggestions I made every other part worth using on its own and let the data build up as a side effect. The biggest investment was the library: over 7,000 beans with roaster, origin, process and tasting notes. That made it a way to discover coffee and lets Tazzina suggest a brew without anyone else's brews.

Tazzina community suggestion for a Chemex brew on a Sette 270 grinder Tazzina community suggestion for an Orea pour-over brew, anchored to a specific grinder Tazzina community suggestion for an espresso brew, anchored to a specific grinder
Tazzina search screen with filters for roast, tasting notes, origin, process, and varietal Tazzina roaster page for Bigface listing its beans with origin, tasting notes, and roast level Tazzina screen for scaling a brew to twice the dose and water at the same ratio

What did not work

I first used OCR to pull out only the roaster and bean name. The results were unreliable. An LLM was more accurate but slower and more expensive. I went with something simpler: matching against every word OCR found on the bag. Once the library had metadata for each bean, scans had plenty of fields to match on and I dropped the stored words entirely.

Managing the library

Verifying a bean in the Convex dashboard meant five tabs and rows of JSON. So I built an admin console that puts the review queue, merging, web search and color checks in the order I work through them. I chose not to spend design time on it. It has one user, so it's dense and follows my own mental model.

Tazzina admin console showing the grinder catalog and per-grinder range settings Tazzina admin console showing bean card color selection and contrast checking

Design

Most of the design work was deciding what to leave out. I said no to puck prep instructions and a learning hub because they would have turned Tazzina into an espresso course. I said no to an inline camera UI. It looked good but did little for users and had rough edges I couldn't get right, so I used the native camera instead.

I also held back a central place for pour-over recipes. I didn't need one until I got a Hario Switch, and I didn't want recipes to pull the app's weight away from brews. Recipes are coming soon, but as something you follow for a bean rather than entries that stand on their own.

I wanted the beans to be the hero of the app. Coffee bags already have a strong visual language and I let it define the look of the product. Bean cards show your own photo of the bag as a small polaroid. They take their colors from the bag and use subtle 3D motion so they feel like objects you could pick up.

The same cards are on Apple Watch. I reach for it more than I expected when my phone is in another room.

Tazzina Apple Watch app showing a collections list and the current beans with their brews

After launch

People were signing up but not adding beans. I suspected they couldn't find their bean, brewer or grinder and gave up. I can't talk to people who left, so I reached out to users who had submitted beans and saved brews soon after signing up to understand how they brew. They told me their brew history mattered and needed to be clean, so I added a way to clean up wrong entries. Onboarding now leads people to set up their gear or start from a bean. I'm measuring how many new users add a bean, but it's too early to tell.

For grinders I let people submit missing ones for me to review and set up a recurring task to find new ones on the market. Neither moved the numbers. What did was adding the latest grinders that simply weren't in the library yet.

For beans a daily AI catalog refresh keeps the library growing. People now find their bean already there. Beans created by users that need verification dropped from 7–10 a week to 1–2. Exact matches from searches and scans went up, and searches and scans with no match halved within a month.

beans a week needing verification, down from 7–10
1–2
fewer searches and scans with no match within a month
50%

Some people added beans but no brews. A blank brew screen asks a lot. Tazzina now uses an increasing number of heuristics to show a starting recipe that's accurate for their setup and the way they brew.

Active users come back to update their brews 5–10 times a month. These visits are spread out, not attempts made one after another while dialing in. Beans change as they age and brews change with them.

With no marketing at all, SEO pages that answer a coffee question first and then lead to the app bring in 1–3 new users a day.

returns per active user each month to update a brew
5–10
new users a day from search alone, with no marketing
1–3

What's next

The main question is whether Tazzina cuts dial-in attempts for other people the way it did for me. In my own use a new bag went from 2–5 attempts to 1–2. I'm measuring attempts per bean for real users now, but there isn't enough data yet.

After that comes a Pro tier. People with good espresso machines are the most likely to pay for extra variables and bean management. A store for buying beans comes after that.