Inspiration

Anyone who's tried to grab a restock a sneaker drop, a GPU, baby formula during a shortage, a sold-out console already knows that the official "in stock" indicator on a retailer's site is frequently hours stale. The actual source of truth lives informally, scattered across Discord servers and restock-alert bots on X, none of which are local, verified, or built as an actual product.

When we sat down with the AWS Databases + Vercel stack, the obvious DynamoDB demo was a perishable-listing marketplace: post something, someone claims it, TTL deletes it when it expires. It's a clean pattern, but it's also the first idea everyone reaches for with TTL "expire and delete." We wanted TTL to do something more interesting: not just decide when a piece of information disappears, but continuously describe how much you should trust it right now. That reframing decay as a live signal instead of a binary on/off switch is where Blip came from.

What it does

Blip is a crowdsourced, real-time "is it actually in stock" feed. Shoppers report sightings item, category, store, neighborhood and everyone nearby sees a live feed of what's available right now. Every sighting fades visually as it ages: bright and glowing when it's fresh, dimming through warm yellow, and finally fading to gray as it approaches expiry. Anyone can hit "Still there?" to confirm a sighting, which pushes its expiry forward and snaps it back to full brightness the database state and the UI state are the same thing, rendered live.

On top of that core loop, Blip tracks scout streaks and trust tiers (bronze/silver/gold, based on confirmed report history), surfaces cross-area trending categories, and supports "watch" alerts for a category in an area.

How we built it

The frontend is a Next.js app generated through v0.app React, TypeScript, Tailwind CSS, and shadcn/ui components, styled to a deliberately non-default dark "signal" palette (near-black backgrounds, signal-orange and warm-yellow accents, a monospace face reserved only for live numeric data) instead of the blue/violet gradient look most AI-generated apps default to.

The backend is a single Amazon DynamoDB table, provisioned directly through the Vercel Marketplace AWS Databases integration Vercel issues short-lived credentials via OIDC, so there's no manual IAM setup and nothing to hand-paste into environment variables. The schema is a deliberate single-table design: sighting records keyed by area and timestamp, user profile records, one row per confirmation, and a TrendingIndex GSI keyed by category for cross-area trending queries.

The centerpiece is the TTL mechanic. Every sighting gets an expiresAt attribute (30 minutes out). Rather than just letting that value sit there until DynamoDB's TTL process deletes the item, we compute a live confidence score at read time:

confidence=clamp(max⁡(0, expiresAt−now)1800+min⁡(0.3, 0.1×confirmations)+trustBoost, 0, 1)\text{confidence} = \text{clamp}\left(\frac{\max(0,\ \text{expiresAt} - \text{now})}{1800} + \min(0.3,\ 0.1 \times \text{confirmations}) + \text{trustBoost},\ 0,\ 1\right)confidence=clamp(1800max(0, expiresAt−now)​+min(0.3, 0.1×confirmations)+trustBoost, 0, 1)

Each confirmation runs a real UpdateItem that extends expiresAt, which is what produces the "snap back to brightness" moment in the UI. We built the app in focused, sequential prompts into v0 schema first, then report flow, then feed, then confirm logic, then the gamification and trending layers pushing to GitHub after each working stage so we always had a rollback point.

Challenges we ran into

The biggest recurring challenge was keeping v0 anchored to our schema. Left alone, it would happily generate a perfectly reasonable but generic data model we had to be explicit and repetitive about the exact PK/SK/GSI/TTL design rather than letting the tool improvise, especially once we started layering in confirmations and trending on top of the base sighting table.

The decay formula itself took a few passes to feel right. An early version made cards fade too quickly to read in a demo and too slowly to feel meaningfully "live" during normal use we ended up tuning the 30-minute window and the confirmation boost specifically around what looks convincing on camera, not just what's mathematically tidy.

Working under a hard five-day deadline forced constant scope triage. We deliberately cut real geocoding/maps in favor of a fixed area list, skipped a full notification pipeline in favor of an in-app simulation, and kept auth minimal all so we could spend the saved time polishing the one interaction that actually carries the whole pitch: a card fading, then reviving.

Accomplishments that we're proud of

Turning a TTL attribute into a continuously meaningful, visible piece of product design not a cleanup mechanism running invisibly in the background, but something a user can watch happen on screen is the thing we're most proud of. It's a genuinely different use of the primitive than "delete the expired listing," and it gave us a single-table design with two real access patterns instead of one obvious one.

We're also proud of how distinct the visual identity ended up looking given the timeline a dark, instrument-panel feel with a signature glow/decay treatment, rather than the generic AI-generated-dashboard look that's easy to default into when you're moving fast.

What we learned

DynamoDB's TTL is a more expressive primitive than "automatic cleanup" if you compute derived state from the time remaining instead of only branching on whether the item still exists. We also came away with a much clearer sense of how far the v0 + Vercel + AWS Databases integration has closed the old "frontend in minutes, backend in 40 hours" gap provisioning and connecting to DynamoDB took minutes, not a separate IAM/console detour but it still rewards (and arguably requires) handing the tool an explicit, opinionated schema rather than trusting its default guess, especially once judging criteria specifically reward "deliberate architecture."

What's next for Harvest

Real corroboration signals lightweight photo proof on a sighting, or an optional official "we just restocked" confirmation API for participating stores.

Push and email watch alerts through a transactional provider, replacing the in-app simulation we shipped for the demo.

A "Store Restock Score" a rolling reliability score per store derived from historical sighting timestamps, turning raw event data into a predictive signal (e.g., "this store typically restocks Tuesdays around 9am"). Real geolocation in place of the fixed area list.

A retailer self-serve "verified restock" boost as a monetizable layer alongside the free consumer tier the natural bridge from this B2C build toward a B2B revenue line.

Built With

Share this project:

Updates