Demo project — All data is simulated. The backend auto-generates 30 days of mock metrics, events, and alert rules on startup, and continuously broadcasts new fake data every 5 seconds via WebSocket. No external services or real data sources required.
Internal dashboard for real-time operations monitoring. Built with Next.js 15 (App Router), FastAPI, WebSockets, and SQLite.
┌──────────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│ │ KPI Cards│ │ Charts │ │ Events │ │ Alerts │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌────┴────────────┴────────────┴─────────────┴───────┐ │
│ │ React Query + WebSocket Hook │ │
│ └────────────────────┬───────────────────────────────┘ │
└───────────────────────┼──────────────────────────────────┘
│ HTTP + WebSocket
┌───────────────────────┼──────────────────────────────────┐
│ FastAPI Backend │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│ │ REST API │ │WebSocket │ │ Seeder │ │ Alert Eng │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬─────┘ │
│ └────────────┴────────────┴─────────────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ │ SQLite │ │
│ └───────────┘ │
└──────────────────────────────────────────────────────────┘
| Layer | Technology |
|---|---|
| Frontend | Next.js 15 (App Router), Tailwind CSS, Recharts |
| State | React Query (TanStack Query v5), custom WebSocket hook |
| Auth | NextAuth.js v4 (JWT + Credentials provider) |
| Backend | FastAPI (Python), aiosqlite |
| Real-time | Native WebSocket with periodic broadcast |
| Database | SQLite |
Operations teams waste hours switching between monitoring tools to get a unified view of system health. OpsDash centralizes metrics, events, and alerting in one real-time interface — built to demonstrate rapid full-stack delivery from database schema to live UI in under a week.
- Node.js 18+
- Python 3.10+
./run.shStarts both backend (port 8000) and frontend (port 3000) concurrently.
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8000On first run, the seed script auto-generates 30 days of realistic mock data (~720 data points per metric, ~300 events).
cd frontend
npm install
npm run devOpen http://localhost:3000.
| Role | Password | Capabilities | |
|---|---|---|---|
| Admin | [email protected] |
admin123 |
Full access: manage alert rules, reset data feed |
| Viewer | [email protected] |
viewer123 |
Read-only dashboard view |
- KPI Cards — 4 key metrics (active users, revenue, error rate, avg response time) with animated counters and trend badges showing % change vs previous period
- Live Chart — Time-series area chart with metric selector and date range picker (1h / 24h / 7d / 30d). Updates every 5 seconds via WebSocket
- Events Table — Paginated, filterable feed of system events (info / warning / error) with search and row animations
- Alert System — Threshold-based alert rules (gt, lt, gte, lte, eq) evaluated every broadcast cycle. Triggered alerts appear as persistent banners
| Metric | Description | Base Value |
|---|---|---|
active_users |
Concurrent active users | ~150 |
revenue_today |
Revenue in current day | ~$8,000 |
error_rate |
Error percentage | ~2.5% |
avg_response_time |
Average API response time (ms) | ~150ms |
requests_per_second |
Incoming requests/s | ~60 |
cpu_usage |
CPU utilization % | ~50% |
memory_usage |
Memory utilization % | ~65% |
disk_io |
Disk I/O metric | ~35 |
- JWT authentication — Tokens issued via NextAuth, validated on protected API calls (admin endpoints)
- Rate limiting — Per-IP (60 req/min general, 5 req/min for login) and per-user (120 req/min)
- Security headers — X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy
- Role-based access control — Admin-only endpoints for alert management and data reset
- Dark / light / system theme toggle
- Skeleton loaders for every data state
- Responsive layout: sidebar navigation collapses to bottom tab bar on mobile
- Animated number counters on KPI updates
- Focus and active states on all interactive elements
- Login (5s) — Show both accounts. Admin gets full access, Viewer is read-only.
- KPI Cards (10s) — Point to the animated counters. Numbers count up when data changes. Trend badges show % change vs previous period.
- Live Chart (15s) — Select a metric from the dropdown. Change date range (1h → 24h → 7d → 30d). Watch the chart update live — new data point every 5 seconds.
- Events Table (10s) — Filter by type (Info/Warning/Error). Search for "database". Show pagination. New events slide in with animation.
- Alert Rules (10s) — As Admin, create a new alert rule (e.g., CPU > 90%). Toggle existing rules on/off. Show how alerts trigger and appear as banners.
- Theme & Responsive (10s) — Toggle dark/light mode. Resize browser to show sidebar → bottom nav transition.
DB_PATH=dashboard.db
WS_INTERVAL=5
RATE_LIMIT_MAX=60
RATE_LIMIT_WINDOW=60
LOGIN_RATE_LIMIT_MAX=5
LOGIN_RATE_LIMIT_WINDOW=60
USER_RATE_LIMIT_MAX=120
USER_RATE_LIMIT_WINDOW=60
ALLOWED_ORIGINS=http://localhost:3000
NEXTAUTH_SECRET=your-secret-here
NEXTAUTH_SECRET=your-secret-here
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_WS_URL=ws://localhost:8000/ws/metrics
NEXT_PUBLIC_API_URL=http://localhost:8000
v1/
├── run.sh # Starts both backend + frontend
├── backend/
│ ├── main.py # FastAPI app: REST endpoints, WebSocket server, broadcast loop, alert engine
│ ├── database.py # SQLite schema (4 tables), seed script (30 days of mock data)
│ ├── auth.py # JWT verification, role checks, per-user rate limiting
│ ├── requirements.txt
│ └── .env
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── (dashboard)/
│ │ │ │ ├── page.tsx # Main dashboard page
│ │ │ │ ├── analytics/ # Multi-metric charts view
│ │ │ │ ├── alerts/ # Alert rule management (admin)
│ │ │ │ └── settings/ # Theme + account settings
│ │ │ ├── login/ # Authentication page
│ │ │ ├── api/auth/ # NextAuth route handler
│ │ │ ├── layout.tsx # Root layout + fonts
│ │ │ ├── providers.tsx # React Query + Session + Theme providers
│ │ │ ├── globals.css # Design tokens + utilities
│ │ │ └── not-found.tsx # 404 page
│ │ ├── components/
│ │ │ ├── Header.tsx # Top bar with user menu
│ │ │ ├── Sidebar.tsx # Desktop navigation
│ │ │ ├── MobileNav.tsx # Bottom tab bar (mobile)
│ │ │ ├── KPICards.tsx # Metric cards with animated counters
│ │ │ ├── MetricChart.tsx # Recharts area chart with range selector
│ │ │ ├── EventsTable.tsx # Paginated event feed
│ │ │ ├── AlertBanner.tsx # Active alert notification banners
│ │ │ ├── AlertRules.tsx # CRUD interface for alert rules
│ │ │ └── ThemeProvider.tsx # Dark/light/system theme context
│ │ ├── hooks/
│ │ │ ├── useWebSocket.ts # WebSocket connection with auto-reconnect
│ │ │ └── useAnimatedValue.ts # Smooth number counter animation
│ │ ├── lib/
│ │ │ ├── api.ts # Fetch wrapper for backend API
│ │ │ └── auth.ts # NextAuth configuration + credentials provider
│ │ └── types/
│ │ └── index.ts # Shared TypeScript interfaces
│ ├── package.json
│ ├── tailwind.config.ts
│ ├── next.config.js
│ └── tsconfig.json
└── README.md
The SQLite database contains 4 tables:
- metrics — Time-series data:
id,metric_name,value,timestamp - events — System events:
id,event_type(info/warning/error),message,source,metadata,timestamp - alert_rules — User-defined rules:
id,metric_name,condition(gt/lt/gte/lte/eq),threshold,enabled - active_alerts — Triggered alerts:
id,rule_id,metric_name,current_value,threshold,condition,triggered_at,resolved_at
All tables have indexes on commonly queried columns for performance.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/kpi?range=24h |
Yes | KPI summary with trend data for 4 key metrics |
| GET | /api/metrics/{name}?range=24h |
Yes | Time-series data points for a specific metric |
| GET | /api/events?page=1&type=error&search=term |
Yes | Paginated events with optional type filter and search |
| GET | /api/alerts/rules |
Yes | List all alert rules |
| POST | /api/alerts/rules |
Admin | Create a new alert rule |
| PATCH | /api/alerts/rules/{id} |
Admin | Update an alert rule (enabled, threshold, condition) |
| DELETE | /api/alerts/rules/{id} |
Admin | Delete an alert rule |
| GET | /api/alerts/active |
Yes | List currently triggered (unresolved) alerts |
| POST | /api/alerts/resolve/{id} |
Yes | Mark an alert as resolved |
| POST | /api/reset |
Admin | Delete all data and reseed with fresh mock data |
| GET | /api/health |
No | Health check with active WebSocket connection count |
| WS | /ws/metrics |
No | Real-time metric stream (broadcast every 5s) |