Kurubu Matcha
Self-made end-to-end e-commerce for kurubu matcha.
05.2026
View Project
Why I Built Our Own Store Instead of Paying Marketplaces 30%
I started Kurubu Matcha because I wanted ceremonial-grade Japanese leaf in Indonesia without the boutique markup. The part nobody talks about: once you actually sell here, the bigger tax isn’t the importer. It’s the platform.
My love for matcha started in high school. Back then authentic Japanese-grade stuff was hard to find in Indonesia — the category just wasn’t big yet. Once I started working, I wanted a way to bring the real thing over. We tasted our way through Kyoto Uji, Yame, Kagoshima, and kept going until we found profiles that actually drink well: vivid color, soft sweetness, umami, enough nuttiness that you don’t need to drown it in milk.
Kurubu’s goal stayed simple. Ceremonial grade that people can afford for everyday cups, not just café flexes. We still sell on Shopee and Tokopedia because that’s where a lot of Indonesian buyers already are. But those channels have a cost that shows up on every tin.
The fee that forced the price up
Indonesian e-commerce platforms love “free delivery.” Customers love it too. Someone still pays for it though, and for a small brand that someone is you.
To keep free shipping and stay competitive on marketplace rankings, we were looking at roughly 30% of profit getting eaten just to fulfill that promise. Not marketing. Not ads. Delivery theater.
So we had two options: keep marking up prices so the marketplace math still worked, or build a place where we set the rules. I chose the second.
That’s why kurubumatcha.com exists as a real store, not a brochure with a “buy on Shopee” button.
What “our own store” actually means
I didn’t want a pretty landing page. I wanted the same operational loop we run by hand — catalog, stock, orders, payment proof, shipping, tracking — except it lives in one system I own.
So I built it end to end:
For customers
- Browse ceremonial matcha with origin, cultivar, harvest, taste scores, and real stock
- Cart that sticks around
- Checkout with Indonesian address levels and live courier rates
- Bank transfer / QRIS payment instructions
- Upload payment proof, get status updates, track the parcel, confirm delivery
For me (admin)
- Full product CRUD — create, edit, delete, image upload, quick price/stock updates
- Payment destination CRUD — bank accounts and QRIS configs without redeploying
- Order inbox with proof review (approve / reject with a reason)
- Fulfillment: courier, tracking number, printable shipping label
- Emails on order, payment, and shipment
The flow looks roughly like this:
browse → cart → checkout + shipping rate → place order → transfer / QRIS → upload proof → I verify → pack & ship → customer tracks
That’s not a demo. That’s how Kurubu ships.
What I built it with
Stack-wise, this is a TypeScript monorepo (Turborepo + pnpm) with a Next.js App Router storefront, React on the front, Supabase for Postgres / auth / storage (with RLS), RajaOngkir for domestic and international shipping quotes, and Resend for transactional email.
Payments are intentionally local: admin-configured bank transfer and QRIS, proof upload to private storage, then human verification. That matches how a lot of Indonesian buyers already pay, and it keeps us off gateway fees while we’re still small.
I care less about the buzzwords than about the outcome: when a café or a home drinker buys direct, more of the price goes to the leaf and the logistics — not to subsidizing marketplace free-shipping games.
What changed after we went live on our own site
Marketplace listings didn’t disappear. They still work as discovery. But direct became the channel where we can price honestly.
If you’re buying from us on the site, you’re not funding a 30% free-delivery tax. You’re paying for matcha that came from Japan, fulfillment from Jakarta, and a checkout I can actually explain.
Building full CRUD and end-to-end payment wasn’t “portfolio engineering.” It was the only way to stop letting platforms decide our margin.
Contributed as Design Engineer
Solo Project
Made using Nextjs, Sanity, MantineUI, Stripe, Supabase
© 2026 Kevin Bryan.
KEVIN
BRYAN