Hey HN. I built dev/brew — a specialty coffee brand where you pay $30, and a bag of mystery coffee ships to wherever you are in the world. You don't know the origin until it arrives. The site is live, the coffee is real, and real orders have shipped. I wanted to write up the technical decisions and the things that surprised me.
TL;DR: Static HTML frontend on Vercel, PayPal for payments, roaster partner handles fulfilment under a white-label arrangement. The whole thing costs approximately $0/month to run outside of the wholesale invoices.
Why This Exists
Two things I believe: specialty coffee buyers are paralyzed by choice, and the best coffee experiences I've had came from trusting a roaster completely rather than selecting from a menu. The mystery bag is a product expression of that belief. Whether the market agrees is what we're testing.
The developer audience is deliberate. We're a group with high discretionary income, strong willingness to pay for things that reduce friction, and a demonstrated preference for products with a distinct point of view. "Unknown origin, $30 flat, ships worldwide" is a cleaner proposition for that audience than a curated menu of twelve SKUs.
The Stack
| Layer | Technology | Why |
|---|---|---|
| Frontend | Static HTML/CSS/JS | No framework, no build step, deploys in seconds, zero cold starts. Thematically correct. |
| Hosting | Vercel | Free tier, global CDN, handles custom 404 routing cleanly, great DX |
| Payments | PayPal fixed-price link | No code to maintain, handles card/PayPal balance worldwide, instant setup |
| Fulfilment | Roaster partner (undisclosed) | White-label arrangement, fresh roast stock, covers international shipping |
| Waitlist | Vercel serverless + Upstash | Single API route, Redis for email storage, no database overhead |
| Design system | Single tokens.css | One source of truth for all pages — no component framework needed |
What Was Hard
the_mystery_constraint
The product premise creates unusual technical constraints. A typical e-commerce site shows the product, then takes the order. We can't show the product — it's unknown until it ships. This means the entire site has to sell the concept rather than the item. Every copy decision, every design decision, flows from this constraint. The site can't answer "what am I buying?" It can only answer "why would I buy this?"
The PayPal fixed-price link was chosen partly because of this constraint. A custom checkout flow would invite feature requests for grind preferences, origin filters, "make it not a mystery." A PayPal button is a hard boundary. There is one product. Here is the price. The button is the interface. This matches the product.
worldwide_without_a_warehouse
Free worldwide shipping at $30 is only viable if the fulfilment cost is already covered. Our roaster partner handles international shipping as part of their wholesale arrangement — we pay a per-order rate that includes packaging and courier, they handle the logistics. We never touch a bag. The model works because specialty coffee roasters have professionalized their B2B infrastructure over the last decade; many have built or adopted API-adjacent fulfilment systems specifically to support white-label wholesale.
The undisclosed roaster is intentional. Naming them would let someone go direct and undercut us on price. The brand and the ordering experience are what we add. The logistics are plumbing.
What Surprised Me
The static site performs absurdly well. No framework, no server-side rendering — just HTML and CSS. Lighthouse scores 97+. Loads in under 700ms on 3G. Every time I think "maybe we need something fancier," the performance data says we don't.
The mystery mechanic is a stronger hook than I expected. The blog post view time is longer for posts that discuss the curation process than for posts that explain the product. People don't need to understand what they're buying — they want evidence that the decision was made well on their behalf.
The hardest design problem was the empty state. We launched before any dispatches shipped. An empty blog feed reads as "nothing happening here." The solution — a deliberate terminal empty state with $ tail -f dispatch.log — reframed the emptiness as something active. Waiting for a signal, not failing to have one.
Open Questions
Happy to answer questions about any part of the stack or the product decisions. Honest feedback welcomed — especially if you've solved any of these problems in your own projects.