A desktop stock market tracker and predictor built with React Router, Vite, and Electron. Tracks live quotes, manages portfolios, and generates AI-powered price predictions using technical analysis.
![Dark theme UI with markets, portfolio, and predictions pages]
- Live Markets — Real-time quotes for stocks, crypto, and indices (via Yahoo Finance). Add/remove any symbol, auto-refreshes every 60 seconds. Click any row for a detailed side panel with a 90-day price chart, OHLC stats, and predictions.
- Predictions — Statistical price projections using Linear Regression, Bollinger Bands, RSI, and MACD. Shows bear/base/bull price targets with a confidence score.
- Portfolio Manager — Track holdings across multiple portfolios. Shows market value, cost basis, and unrealized P&L per holding. Requires a PostgreSQL database (see setup below).
- React Router v7 + Vite — fullstack web framework with SSR
- Hono — server runtime
- Electron — desktop wrapper
- Recharts — charts
- Tailwind CSS — styling
- Neon — serverless PostgreSQL (for portfolio feature)
- Node.js v18+
- npm v9+
cd apps/web
npm installnpm run electron:devThis starts the Vite dev server on port 4000 and opens it in an Electron window automatically.
npm run devThen open http://localhost:4000.
Create a .env file in apps/web/ (one already exists with a placeholder token):
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Optional | Neon PostgreSQL connection string. Only needed for the Portfolio feature. |
Without DATABASE_URL, the Markets and Predictions pages work fully — only Portfolio will show an error.
If you want the Portfolio feature, create a free database at neon.tech, then run this SQL to set up the tables:
CREATE TABLE portfolios (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE holdings (
id SERIAL PRIMARY KEY,
portfolio_id INTEGER REFERENCES portfolios(id) ON DELETE CASCADE,
symbol TEXT NOT NULL,
shares NUMERIC NOT NULL,
average_cost NUMERIC NOT NULL
);Then add your connection string to .env:
DATABASE_URL=postgres://...
apps/web/
├── electron/
│ └── main.cjs # Electron main process
├── src/
│ ├── app/
│ │ ├── markets/ # Live quotes page
│ │ ├── portfolio/ # Portfolio manager page
│ │ ├── predictions/ # Price predictions page
│ │ ├── api/
│ │ │ ├── quotes/ # GET /api/quotes
│ │ │ ├── history/ # GET /api/history
│ │ │ ├── predict/ # GET /api/predict
│ │ │ └── portfolios/ # CRUD /api/portfolios
│ │ └── layout.jsx
│ └── components/
│ └── Navigation.jsx
└── package.json
Predictions are purely statistical — not financial advice.
| Indicator | Usage |
|---|---|
| Linear Regression | Projects 90-day price trend forward |
| Bollinger Bands | Sets bear/bull volatility envelope |
| RSI (14-period) | Detects overbought/oversold conditions |
| MACD | Identifies momentum shifts |
| Confidence Score | Weighted by trend strength, RSI extremes, and volatility |
| Command | Description |
|---|---|
npm run electron:dev |
Run as desktop app (starts dev server + Electron) |
npm run dev |
Run in browser only |
npm run build |
Build for production |
npm run typecheck |
Type check with TypeScript |
Price predictions are statistical projections based on historical data and technical indicators. They are not financial advice. Past performance does not guarantee future results.