Ecuador — Cuenca
Projects

Traza — A coffee tasting notebook, from origin to your taste

Traza — A coffee tasting notebook, from origin to your taste
September 30, 2026
Traza is a coffee tasting notebook — de origen a tu gusto, from origin to your taste. Every coffee you try becomes a pour: a page in your field notebook that captures the coffee, how you brewed it (method, dose, yield, grind, temperature, time, ratio), an SCA cupping score, your flavour notes, and where you drank it. Over time those pours become a taste profile — Mi Traza — that tells you what to try next, links you to the people who grew the coffee, and lets you buy it from them directly. It is two things built to fit together: a Flutter app for iOS, Android and web, and a companion website. I designed and built both, and it is shipping as a TestFlight beta. Think of it as "Untappd for coffee," but pointed at traceability and the grower rather than just the check-in. Specialty coffee drinkers taste constantly and remember almost none of it. You have a brilliant cup, you mean to note the roaster and the process, and a week later it is gone. Meanwhile the people who actually grew the coffee are invisible at the point you fall in love with it. Traza closes both gaps. For the drinker it is a memory and a palate map: what did I try, what did I love, what do I try next. For the grower and roaster it is a direct line to the person enjoying their coffee — a verified page, a catalogue, and fair-trade sales without a middleman. The tasting notebook is the hook; the origin connection is the point. One architecture, built to swap its backend. The whole app runs behind a single repository interface. An in-memory seeded implementation runs the entire experience with sample data, and a Firestore implementation drops in behind the exact same interface with no UI changes. That seam meant the screens could be designed and tested against realistic data long before the backend existed, and the move to real accounts never touched the UI layer. A real domain model. The data is modelled the way coffee actually works: a roaster sells coffees, a café is a place, a brew guide is a timed recipe, a cupping score is the full SCA form scored 0–100, and a pour is the check-in that ties a coffee, a preparation and a rating together. That rigour is what lets the app be both a casual check-in and a serious cupping tool, depending on who is holding it. A genuine social product, not a list app. It has a feed, discovery, follows, likes and comments, and a shelf of the coffees you have saved. All of the social mechanics that have to be trustworthy — the notifications, the aggregate counts, the moderation — run server-side in Cloud Functions rather than in the client: following someone notifies them, a like or comment notifies the author (never for your own, never for draft pours), reports are handled, and admins can broadcast to a chosen audience. Putting that logic on the server is what stops counts from lying and notifications from being spoofed. Two kinds of account. Alongside personal accounts there is a business side for roasters and cafés: a claimable, verified page with a catalogue, coffee insights, an "on bar" menu and a venue page. A claim is reviewed by an admin, and approval stamps the commercial profile onto the account — so a verified roaster page means something, because a person checked it. Security that lives in the database. Firestore rules scope personal and social data to its owner, let any signed-in user contribute to the shared catalogue (the contribute-a-coffee flow depends on it) while allowing only the contributor, the roaster's owner or an admin to edit, and permit nothing to be deleted. The rules are their own reviewed artifact, with the production hardening written down as explicit to-dos rather than assumed. Traza does not look like a database, which is the whole point. The design language — Cuaderno del Valle, the valley notebook — is warm paper and charcoal ink with crimson and gold accents, hand-drawn wobbly borders, taped-polaroid photos, and handwritten Caveat annotations over a Cormorant Garamond display serif. Logging a coffee should feel like writing in a well-worn field journal, not filling in a form. The same language carries from the app into the website, so the product feels like one object across every surface. The companion site, built with Next.js and fully prerendered to static HTML, does three jobs at once.
  • It sells the idea — an editorial, forest-green, Apple-style scrolling page with the Traza fingerprint mark that explains taste-matched discovery, learning a coffee's origin, and buying straight from the grower on fair-trade terms.
  • It is the public face of the app's content. Pours, coffees and profiles have real web pages (/p, /c, /u), so when someone shares a pour it opens as a proper page with correct previews — the share-a-pour loop lands on the web, then an "open in app" deep link hands the visitor to the app.
  • It captures demand with a beta waitlist and carries the unglamorous essentials a real product needs: privacy, terms, an admin surface, and English/Spanish throughout.
The marketing site is live at traza-web-amber.vercel.app.
  • App: Flutter, Riverpod for state, go_router for navigation, one codebase for iOS, Android and web.
  • Backend: Firebase — Auth, Firestore, Storage, Cloud Messaging and Crashlytics, with Cloud Functions (Node) for notifications, aggregate counts and moderation.
  • Architecture: a repository seam with interchangeable in-memory and Firestore implementations; hand-written Firestore security rules with their own test suite; 32 test files across the app.
  • Website: Next.js (App Router), statically prerendered, with Firebase for the waitlist and public profile pages, bilingual (ES/EN).
  • Release: Fastlane with an App Store Connect API key for hands-off TestFlight builds; internal and external beta tracks.
Designing against a backend that didn't exist yet. The repository seam was the highest-leverage decision in the project. By making the UI depend on an interface rather than Firestore, the entire app could be built, demoed and tested on seeded data, and the real backend slid in underneath without a UI rewrite. It is the difference between "we'll design it once the API is ready" and designing from day one. Trust has to be server-side. In a social product the tempting shortcut is to compute counts and fire notifications from the client. That is exactly how counts drift and notifications get faked. Moving every trust-sensitive mechanic into Cloud Functions was more work and the only honest way to build it. A verified page is a human decision. The claim-and-verify flow for roasters and cafés only means something because an admin reviews it and approval literally stamps the profile. Designing that moderation path — claims, resolutions, broadcasts, reports — was as much of the product as the tasting screens. Beauty is a retention feature here. A tasting app lives or dies on whether people keep logging. The notebook aesthetic is not decoration; it is the reason opening the app feels like a small ritual rather than data entry, and rituals are what bring people back. A working, two-sided coffee product in beta: a tasting notebook that remembers every cup and turns it into a palate, a social layer that connects drinkers, and a verified business side that puts roasters and growers on the other end of that connection — all under one hand-drawn visual language, shared between a Flutter app and a static companion site. The architecture is built to scale from seeded demo data to real accounts without a rewrite, and the whole thing is designed around a single promise: from origin, to your taste.