{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreigfnzoa7ysy43jym365otr4lr6fijv22gydqt3ktzctoxfehqetyy",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mphoqgfuggp2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibqxcjjysajod24xonykw7xhjqiwyxhe7sqv2zyueps7c2xdou25q"
    },
    "mimeType": "image/webp",
    "size": 186262
  },
  "path": "/himaatluri/building-brewcore-espresso-tracking-on-vercel-dynamodb-and-amazon-bedrock-3hmf",
  "publishedAt": "2026-06-29T23:36:29.000Z",
  "site": "https://dev.to",
  "tags": [
    "aws",
    "h0hackathon",
    "bedrock",
    "serverless",
    "BrewCore",
    "Live Demo",
    "GitHub Repository",
    "Architecture Deep-Dive Docs",
    "H0 Hackathon - Hack the Zero Stack with Vercel and AWS Databases"
  ],
  "textContent": "##  Beyond the Timer: How I Built BrewCore for the H0 Hackathon\n\nHome espresso is a paradox. Baristas obsess over the micro-details the gram weight, the seconds on the clock, the pressure profile-but we usually track it all on sticky notes or fragmented mental maps. When that morning shot turns sour, we don’t have a database to query; we have a bad cup of coffee and a Reddit thread from 2019.\n\nFor the **H0 Hackathon** , I wanted to bridge that gap. I've built **BrewCore** : a full-stack coffee companion that treats an espresso setup like the precision instrument it is.\n\n###  The Problem: Espresso is Data, Not Just Caffeine\n\nMost coffee apps are glorified timers. I wanted a system that understands the _variables_ :\n\n  * **The Inventory:** How many grams of that Ethiopian light roast are left?\n\n  * **The Science:** What happened last Tuesday when a barista ground finer but lowered the temp?\n\n  * **The Coach:** How do you fix a sour shot using a specific machine and history?\n\n\n\n\nI set out to build a platform that turns home baristas into data scientists. And I wanted to do it with a stack that is as robust as it is clean: Next.js 15, Vercel, Amazon DynamoDB, and Amazon Bedrock.\n\n##  The Serverless Architecture\n\nTo achieve absolute zero-infrastructure management during development, I mapped out a clean separation of concerns between my hosting platform and cloud data layers.\n\n###  End-to-End Data Flow\n\nAs detailed in my system architecture, the application relies on four core stages to handle traffic securely and efficiently:\n\n  1. **Browse & Log Shots:** The end-user interacts with a responsive React PWA hosted on Vercel. All client interactions communicate via secure HTTPS directly to Next.js 15 Server Actions.\n\n  2. **Authenticate:** Security is managed entirely at the edge. The Amplify client SDK handles secure user sign-ins and session tokens via an **Amazon Cognito User Pool**.\n\n  3. **Persist Data:** Server Actions eliminate the need for a separate API Gateway or dedicated Lambda layer. The application uses the **AWS SDK v3** to read and write records directly into my specialized data tables.\n\n  4. **AI Coaching:** When a user requests dial-in assistance, the app bundles their historical brewing data and utilizes the **Amazon Bedrock Converse API** to invoke the high-performance `nova-micro` model.\n\n\n\n\n##  DynamoDB: Multi-Table Design Principles\n\nMost people reach for SQL when they need data relationships. I went the other way, modeling my storage strictly around **how the UI actually behaves.**\n\nInstead of dealing with resource-heavy scans, I created eight dedicated tables optimized for $O(1)$ key-value lookups and targeted queries using Global Secondary Indexes (GSIs):\n\n  * `users` - Profiles and customizable setup preferences.\n  * `beans` - Granular tracking of inventory grams remaining, roaster data, and low-stock indicators.\n  * `shots` - Fully detailed extraction parameters (grind, dose, yield, time, and flavor profiles).\n  * `interactions` & `comments` - Handles social metrics like likes and feedback counters on the community feed.\n  * `user_stats` - Pre-aggregated counter arrays to avoid expensive runtime calculations.\n  * `follows` & `product_states` - Manages the social graph and handles client-side state flags for UI element dismissal.\n\n\n\n###  The Developer Workflow: Mock vs. Real Cloud\n\nThe biggest bottleneck in hackathons is usually waiting for cloud infrastructure to provision. I solved this with a **dual-backend interface**. I built a local `localStorage` mock that perfectly mirrors my structural DynamoDB types. I developed the entire UI offline, and when I was ready, I flipped one environment variable to shift traffic to my production AWS tables.\n\n##  Teaching AI to Pull a Perfect Shot\n\nGeneric AI tips are useless for espresso-\"grind finer\" is completely unhelpful advice if the model doesn't know a barista's starting baseline.\n\nBy feeding my **Bedrock (Nova Micro)** model a structured context payload of the user's explicit profile-bean history, machine parameters, and recent extraction logs, I transformed generic LLM behavior into a personalized barista coach. It doesn't guess; it performs direct trend analysis on the database entries.\n\n##  Technical Lessons Learned\n\n  * **Next.js Server Actions need robust global error handling**\nWhen bypassing an API Gateway/Lambda layer to call DynamoDB directly from Next.js Server Actions, traditional HTTP status code safety nets disappear. If a write fails or an IAM credential expires, the Server Action can silently fail or crash the client components if the rejection isn't caught cleanly. I learned to wrap my `DatabaseOperations` client in a strict, uniform error-handling wrapper that gracefully maps AWS SDK exceptions to typed, user-friendly UI alerts without leaking sensitive cloud configuration details.\n\n  * **DynamoDB GSIs demand strict primitive data types**\nI hit an immediate roadblock when setting up the community feed query: global secondary index (GSI) keys in Terraform natively expect string (`S`), number (`N`), or binary (`B`) data types. Because I originally modeled shot visibility (`isPublic`) as a standard boolean, my infrastructure provisioning failed on the first apply. I had to pivot and normalize my schema to store booleans as `\"true\"` or `\"false\"` strings, teaching me that NoSQL design means your infrastructure constraints strictly dictate your application logic.\n\n  * **LLMs require rigid prompt grounding, not just long system instructions**\nMy early iterations with Amazon Bedrock (Nova Micro) frequently suffered from recipe hallucinations; when asked how to fix a sour espresso pull, the model would guess generic parameters rather than looking at what the user actually did. I realized that a massive, descriptive system prompt is useless without rigid data grounding. The fix was structured JSON context injection: I began querying the user's specific extraction history and passing a serialized payload of their last 3 shots directly into the prompt context, forcing the AI to act as a data analyst rather than a generic text generator.\n\n\n\n\n##  Resources & Repositories\n\n  * **Live Demo** _(Select \"Instant Demo Access\" in`/auth` for complete access)_\n\n  * **GitHub Repository**\n\n  * **Architecture Deep-Dive Docs**\n\n\n\n\nWhether you are a coffee enthusiast or an engineer seeking a production template for matching Vercel with deep AWS serverless integrations, BrewCore shows that you don't need a massive footprint to ship powerful, cloud-native applications.\n\n**Happy brewing.** ☕\n\n###  Hackathon Submission Disclosure\n\n_This article was created and published for the purposes of entering the H0 Hackathon - Hack the Zero Stack with Vercel and AWS Databases. #H0Hackathon_",
  "title": "Building BrewCore: Espresso Tracking on Vercel, DynamoDB, and Amazon Bedrock"
}