A production-grade full-stack application demonstrating enterprise-level architecture, authentication, and real-time data integration
• Architecture • Features • Tech Stack
Stonks is a sophisticated stock market tracking application that enables users to search thousands of stocks, build personalized watchlists, and receive automated price alerts. Built with modern web technologies and production-ready patterns, this project showcases end-to-end ownership of product development.
Why This Project Matters:
- ✅ Full-Stack Expertise — Seamless integration of frontend, backend, database, and third-party APIs
- ✅ Production Architecture — Scalable design with proper error handling, caching, and security
- ✅ Modern Stack Mastery — Latest Next.js 15 patterns with Server Components and Server Actions
- ✅ Real-World Complexity — Authentication, background jobs, email notifications, and real-time data
- Email/password authentication with Better Auth
- Cookie-based sessions with MongoDB adapter
- Protected routes and API endpoints
- Keyboard shortcut (⌘K / Ctrl+K) for instant search
- Debounced API calls with 300ms optimization
- Preloaded popular stocks for zero-latency UX
- Live results from Finnhub API
- Add/remove stocks with optimistic UI updates
- Duplicate-safe upserts with MongoDB compound indexes
- Real-time synchronization across sessions
- Clean, responsive table layout
- Background job orchestration with Inngest
- Configurable price thresholds (upper/lower bounds)
- Professional email templates with Nodemailer
- Retry logic and failure handling
- Mobile-first approach with Tailwind CSS
- shadcn/ui component library
- Dark theme with consistent design system
- Accessible keyboard navigation
graph TB
A[Client: Next.js App Router] --> B[Server Components]
A --> C[Route Handlers /api/*]
B --> D[Server Actions]
C --> E[MongoDB Atlas]
D --> E
C --> F[Finnhub API]
D --> F
G[Inngest] --> H[Background Jobs]
H --> I[Email Service]
H --> F
E --> J[Indexes & Constraints]
Key Design Decisions:
| Component | Technology | Rationale |
|---|---|---|
| Auth | Better Auth + MongoDB | Cookie-based sessions, scalable adapter pattern |
| Database | MongoDB + Mongoose | Flexible schema, compound indexes for uniqueness |
| API | REST Route Handlers | Clear boundaries, standard HTTP semantics |
| Background Jobs | Inngest | Reliable execution, built-in retries, observability |
| Caching | React cache() |
Server-side memoization, 30-60min revalidation |
Real-time market data with intelligent search
Personalized stock tracking with optimistic updates
Comprehensive stock information and TradingView integration
Professional price alert notifications
Node.js 18+
MongoDB Atlas account (or local MongoDB)
Finnhub API key (free tier available)- Clone the repository
git clone https://github.com/yourusername/stonks.git
cd stonks- Install dependencies
npm install- Configure environment variables
Create .env.local:
# Database
MONGODB_URI="mongodb+srv://username:password@cluster.mongodb.net/stonks"
# Authentication
BETTER_AUTH_SECRET="generate-with-openssl-rand-base64-32"
BETTER_AUTH_URL="http://localhost:3000"
# Finnhub API
FINNHUB_API_KEY="your_finnhub_api_key"
NEXT_PUBLIC_FINNHUB_API_KEY="your_public_key"
# Email (SMTP)
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="your-email@gmail.com"
SMTP_PASS="your-app-password"
SMTP_FROM="Stonks <noreply@stonks.com>"
# Inngest (optional for alerts)
INNGEST_EVENT_KEY="your_inngest_event_key"- Run the development server
npm run devOpen http://localhost:3000 🎉
All endpoints require valid session cookie from Better Auth.
| Method | Endpoint | Description | Request Body | Response |
|---|---|---|---|---|
GET |
/api/watchlist |
Fetch user's watchlist | - | WatchlistItem[] |
GET |
/api/watchlist?symbol=AAPL |
Check if symbol exists | Query: symbol |
{ exists: boolean } |
POST |
/api/watchlist |
Add to watchlist (idempotent) | { symbol: string, company: string } |
{ ok: boolean } |
DELETE |
/api/watchlist |
Remove from watchlist | { symbol: string } |
{ ok: boolean } |
Example Request:
// Add to watchlist
const response = await fetch('/api/watchlist', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ symbol: 'AAPL', company: 'Apple Inc.' })
});// Compound unique index prevents duplicates at DB level
WatchlistSchema.index({ userId: 1, symbol: 1 }, { unique: true });
// Idempotent upsert pattern
await Watchlist.updateOne(
{ userId, symbol },
{ $set: { company, addedAt: new Date() } },
{ upsert: true }
);// Instant feedback with rollback on error
const handleToggle = async () => {
setIsInWatchlist(!isInWatchlist); // Optimistic update
try {
await mutateWatchlist();
} catch (error) {
setIsInWatchlist(isInWatchlist); // Revert on failure
toast.error('Failed to update watchlist');
}
};export const searchStocks = cache(async (query: string) => {
const data = await finnhubFetch(`/search?q=${query}`);
return data;
}, {
revalidate: 3600 // 1 hour cache
});// End-to-end type safety from API to UI
interface WatchlistItem {
symbol: string;
company: string;
addedAt: Date;
userId: string;
}
type ApiResponse = { data: WatchlistItem[] } | { error: string };# Install Vercel CLI
npm i -g vercel
# Deploy
vercel --prodEnvironment Setup:
- Configure all environment variables in Vercel Dashboard
- Connect MongoDB Atlas (whitelist Vercel IPs)
- Enable automatic deployments from
mainbranch
# Build and run with Docker
docker build -t stonks .
docker run -p 3000:3000 --env-file .env.local stonks- ✅ Authentication: Secure cookie-based sessions, httpOnly flags
- ✅ Authorization: User-scoped queries (all watchlist operations filtered by
userId) - ✅ Input Validation: Zod schemas for API request validation
- ✅ Error Handling: Never expose stack traces to client
- ✅ Rate Limiting: Debounced search, API request throttling
- ✅ Environment Secrets: All sensitive data in environment variables
- Real-time quotes via WebSocket integration
- Advanced charts with technical indicators
- Portfolio tracking with P&L calculations
- Social features (shared watchlists, discussions)
- Mobile apps (React Native)
- AI-powered insights with market sentiment analysis
This project deepened my understanding of:
- Scalable Architecture — Designing systems that grow from prototype to production
- Next.js 15 Patterns — Server Components, Server Actions, and the App Router
- Database Design — Modeling relationships, indexes, and constraints for performance
- Background Jobs — Reliable async processing with Inngest
Madhavendranath
Full-Stack Engineer | Building Production-Grade Web Applications
