A customizable financial dashboard application built with Next.js, React, and TypeScript. FinBoard allows users to create, configure, and manage multiple widgets for tracking financial data from various APIs.
- Dashboard Management - Create and customize financial widgets
- Multiple Widget Types - Finance Cards, Data Tables, and Line Charts
- Responsive Grid Layout - CSS Grid-based layout system
- Data Persistence - Auto-save dashboard configuration to localStorage
- Real-Time Updates - Configurable auto-refresh intervals for each widget
- API Integration - Support for Alpha Vantage and Finnhub APIs
- Field Selection - Dynamically select which data fields to display
- Data Caching - Intelligent caching to reduce API calls
- Error Handling - Graceful error messages and fallback states
- UX States - Loading spinners, error messages, and empty states
src/
βββ app/
β βββ dashboard/
β β βββ page.tsx # Dashboard page entry point
β βββ layout.tsx # Root layout component
β βββ page.tsx # Home page (redirects to dashboard)
β βββ globals.css # Global styles
βββ components/
β βββ dashboard/
β β βββ Dashboard.tsx # Main dashboard component
β βββ widgets/
β β βββ FinanceCardWidget.tsx # Stock price card widget
β β βββ TableWidget.tsx # Data table widget
β β βββ ChartWidget.tsx # Line chart widget
β βββ modals/
β β βββ WidgetTypeModal.tsx # Widget type selection
β β βββ WidgetConfigModal.tsx # Widget configuration form
β βββ ui/
β βββ Button.tsx # Reusable button component
β βββ Modal.tsx # Reusable modal component
β βββ Card.tsx # Reusable card component
βββ store/
β βββ dashboardStore.ts # Zustand global state management
βββ services/
β βββ api/
β βββ apiService.ts # API integration (Alpha Vantage, Finnhub)
βββ hooks/ # Custom React hooks (placeholder)
βββ utils/ # Utility functions (placeholder)
βββ types/
βββ widget.ts # TypeScript type definitions
Zustand is used for global state management with automatic localStorage persistence:
useDashboardStore()- Main store hook for widget CRUD operations- Widget management: add, remove, update, reorder
- Layout management with position tracking
- Error and loading state management
- Data caching with 1-minute expiration
Each widget consists of:
- Widget Data Model - Unique ID, type, title, API config, display config, grid layout
- API Configuration - Provider, endpoint, refresh interval
- Display Configuration - Title, selectable fields, formatting options
- Grid Layout - Responsive positioning with width/height
- Service Pattern - Separate service classes for each API provider
- Alpha Vantage - Stock quotes and time series data
- Finnhub - Real-time stock data and candles
- Error Handling - Rate limit detection and user-friendly errors
- Field Extraction - Automatic detection of available data fields
- Node.js 16+ and npm
- API Keys (free tier available):
- Alpha Vantage - Stock market data (demo key: "demo")
- Finnhub - Stock quotes (free tier available)
# Navigate to project
cd finboard
# Install dependencies
npm install
# Configure environment variables
# Copy .env.local and add your API keys:
NEXT_PUBLIC_ALPHA_VANTAGE_KEY=your_key_or_demo
NEXT_PUBLIC_FINNHUB_KEY=your_key_or_demo
# Run development server
npm run dev
# Open http://localhost:3000 in browserDisplays key financial metrics at a glance:
- Real-time stock price and symbol
- Price change with percentage
- Customizable data fields from API
- Auto-refresh with configurable interval (minimum 60 seconds)
- Error states with fallback messages
Best for: Quick overview of individual stock metrics
Shows multiple stocks in a tabular format:
- Searchable and filterable across all columns
- Pagination with 10 items per page
- Column headers for sorting (ready for enhancement)
- Responsive table design
- Client-side data management
Best for: Comparing multiple stocks side-by-side
Visualizes price trends over time:
- Interactive line chart using Recharts
- Time interval selection (Daily, Weekly, Monthly)
- Hover tooltips for detailed data
- Responsive sizing to widget dimensions
- Smooth animations and transitions
Best for: Identifying trends and patterns
Endpoints:
- GLOBAL_QUOTE: Get current stock price
- TIME_SERIES_DAILY/WEEKLY/MONTHLY: Historical price data
Features:
- Free tier: 5 requests/minute, 500/day
- Supports all major stocks (AAPL, GOOGL, etc.)
Endpoints:
- /quote: Real-time stock quotes
- /stock/candle: OHLC candle data
Features:
- Free tier available
- No rate limit for free tier (fair use)
- Real-time data with minimal latency
When configuring a widget:
- User selects API provider and stock symbol
- Click "Test API Connection"
- Service fetches live data from API
- Displays top-level available fields
- User selects fields to display in widget
// Zustand persists to localStorage automatically
- Key: "finboard-store"
- Triggers: Any widget changes
- Restored on page load
- Survives browser refresh and restart// Per-widget intelligent caching
- Cache duration: 1 minute
- Tracks lastDataFetch timestamp
- Returns cached data if valid
- Reduces redundant API callsEdit Tailwind classes in widget components. Example - change card header:
<CardHeader className="bg-gradient-to-r from-blue-500 to-blue-600">In WidgetConfigModal.tsx, modify default or minimum:
const refreshInterval = 300; // 5 minutes
// Minimum: 60 seconds to avoid API rate limitsIn Dashboard.tsx, adjust responsive breakpoints:
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">- Create component in
src/components/widgets/ - Add type to
WidgetTypeinsrc/types/widget.ts - Add to modal options in
WidgetTypeModal.tsx - Update
Dashboard.tsxrender logic
- API Keys - All keys use environment variables (never commit
.env.local) - Client-Side Keys -
NEXT_PUBLIC_prefix indicates these are safe for browser - CORS Protection - APIs handle CORS; no backend proxy needed for demo
- Rate Limiting - Built-in cache prevents excessive API calls
- Error Handling - Never expose raw API errors to users
- Zustand Selectors -
useWidgets(),useSelectedWidget()for fine-grained updates - Lazy Loading - Widgets only fetch data when mounted
- Response Caching - 1-minute cache reduces API load
- CSS Grid - Native browser layout (no heavy JS library)
- React Compiler - Next.js 16 auto-optimization enabled
Each widget manages independent refresh:
useEffect(() => {
fetchData(); // Fetch immediately
// Set interval based on widget config
const interval = setInterval(
fetchData,
widget.apiConfig.refreshInterval * 1000
);
return () => clearInterval(interval); // Cleanup
}, [widget.id, widget.apiConfig]);Future test structure:
tests/
βββ unit/
β βββ store.test.ts # Zustand store logic
β βββ apiService.test.ts # API abstraction
β βββ widgets.test.ts # Widget components
βββ integration/
β βββ dashboard.test.ts # End-to-end widget flow
βββ e2e/
βββ user-flow.test.ts # Complete user journey
npm run build # Creates optimized build
npm start # Runs production server# 1. Connect GitHub repo to Vercel dashboard
# 2. Set environment variables:
NEXT_PUBLIC_ALPHA_VANTAGE_KEY=your_key
NEXT_PUBLIC_FINNHUB_KEY=your_key
# 3. Vercel auto-deploys on git pushFROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm ci && npm run build
ENV NODE_ENV=production
CMD npm start# Build
npm run build
# Run with PM2
pm2 start "npm start" --name "finboard"
pm2 save
pm2 startup
# Or with systemd
sudo systemctl restart finboard- Grid Layout - CSS Grid only; no drag-and-drop yet (planned for Phase 3.2)
- Data Source - Demo data for table/chart (real API integration in progress)
- Field Mapping - Top-level fields only; nested objects not supported yet
- Search - Table search is client-side only
- Export/Import - Configuration backup (planned for Phase 10)
- Drag-and-drop widget reordering with react-grid-layout
- Widget editing after creation
- Multiple portfolio tracking
- Technical indicators (MACD, Bollinger Bands)
- Price alerts and notifications
- Dark mode theme
- User accounts and shared dashboards
- Advanced charting (candlestick, volume)
- Portfolio P&L tracking
- News feed integration
| Criteria | Status | Implementation |
|---|---|---|
| Dashboard Page | β | Header + grid area with responsive design |
| Add Widget Flow | β | Multi-step modal with type selection |
| Widget Types | β | Card, Table, Chart all implemented |
| Configuration | β | API provider, fields, refresh interval |
| API Integration | β | Alpha Vantage & Finnhub services |
| Data Persistence | β | Zustand + localStorage auto-save |
| Real-Time Updates | β | Configurable interval per widget |
| Caching | β | 1-minute smart cache system |
| Error Handling | β | Graceful error messages & fallbacks |
| UX States | β | Loading, error, empty state UI |
| Documentation | β | Comprehensive README (this file) |
| Architecture | β | Scalable folder structure & patterns |
- Next.js Docs: nextjs.org
- Tailwind CSS: tailwindcss.com
- Zustand: zustand-demo.vercel.app
- Recharts: recharts.org
- Alpha Vantage API: alphavantage.co
- Finnhub API: finnhub.io
Version: 1.0.0
Last Updated: January 23, 2026
Status: Production Ready (MVP)
License: MIT
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.