Case study 23 / 26
Puffer
A full-stack stock tracker with watchlists, market search and AI-written news digests delivered by background jobs.
- Status
- In development
- Period
- 2025 — 2026
- Domain
- web · ai
- Language
- TypeScript
- Last push
- 01 APR 2026
- License
- None stated
- Source of claims
- package.json, lib/inngest/functions.ts, lib/better-auth/auth.ts, components/SearchCommand.tsx, app/(root)/stocks/[symbol]/page.tsx
Puffer pairs a Next.js App Router interface — symbol search, per-stock pages built from TradingView widgets, and personal watchlists — with event-driven background jobs that use Gemini to write personalised welcome emails and daily, watchlist-aware market news summaries.
01/The problem
Market data is everywhere; context is not. Puffer is an attempt at a tracker that follows what you watch and tells you, in plain language, what happened to it today.
02/The system
Puffer pairs a Next.js App Router interface — symbol search, per-stock pages built from TradingView widgets, and personal watchlists — with event-driven background jobs that use Gemini to write personalised welcome emails and daily, watchlist-aware market news summaries.
- Next.js App Router to Better Auth
- Next.js App Router to MongoDB
- Next.js App Router to Finnhub
- Better Auth to Inngest
- MongoDB to Inngest
- Finnhub to Inngest
- Inngest to Gemini
- Inngest to Nodemailer
03/Implementation
- 01Per-symbol pages (/stocks/[symbol]) composed from six TradingView widgets: symbol info, candlestick and baseline charts, technical analysis, company profile and financials.
- 02Command-palette symbol search (cmdk) backed by Finnhub, debounced at 300 ms.
- 03Watchlists persisted in MongoDB through a Mongoose model and server actions.
- 04Email-and-password authentication with Better Auth on a MongoDB adapter; sign-up captures country, investment goals, risk tolerance and preferred industry.
- 05An `app/user.created` Inngest event triggers a Gemini-written, profile-aware welcome email sent through Nodemailer.
- 06A daily cron job gathers each user's watchlist news from Finnhub — at most six articles, falling back to general market news — has Gemini summarise it, and emails the digest.
04/Engineering
Durable steps for AI work
Each stage of the digest — fetch users, gather news, summarise, send — is an Inngest step, so a failed model call retries in isolation instead of re-running the whole pipeline.
Graceful degradation per user
Failures are caught per user: one bad watchlist or summary produces an empty result for that user and the batch continues.
Bounded model input
News is capped at six articles per user before prompting, keeping summaries focused and token cost predictable.
05/Interface
No product screenshots are published for this project. The visual above is a code-driven representation of how it behaves, built from the repository source — not a screenshot.
06/Tech stack
- Next.js 15
- React 19
- TypeScript
- MongoDB
- Mongoose
- Better Auth
- Inngest
- Gemini
- Finnhub
- Nodemailer
- Tailwind CSS
- Radix UI
07/Result
Verified outcomes
- Under active development — not presented as production-ready.
08/Links
Next case study
AI Detector →