# Prism v2 Financial overview app. FastAPI backend (yfinance + SQLite watchlist) and Next.js frontend (Plotly chart, ticker search, market bar, watchlist). ## Stack - Backend: Python 3.14+, FastAPI, uvicorn, yfinance, SQLite - Frontend: Node 20+, Next.js (App Router), TypeScript - Production: systemd + nginx (TLS via certbot) ## Layout - `backend/app/` — FastAPI app, services, SQLite watchlist - `frontend/app/` — Next.js App Router; shared types in `frontend/types/api.ts` - `systemd/` — service units (`prismv2-backend.service`, `prismv2-frontend.service`) - `nginx/` — TLS server block (`/api/` → :8001, `/` → :3001) - `scripts/stack.sh` — local dev start/stop/restart/status - `design-system/` — brand tokens + Prism UI kit (mirrored to `frontend/public/design-system/`) ## Environment Copy `.env.example` → `.env`. Current feature set works without keys. - `NEXT_PUBLIC_API_BASE_URL` — leave empty in production (same-origin `/api/*` via nginx) - `FMP_API_KEY`, `FINNHUB_API_KEY` — reserved for future enrichment ## Local Development ```bash # Backend cd backend && python -m venv .venv && .venv/bin/pip install -r requirements.txt .venv/bin/uvicorn app.main:app --reload --host 127.0.0.1 --port 8001 # Frontend cd frontend && npm install NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8001 npm run dev -- --hostname 127.0.0.1 --port 3001 ``` Or use `./scripts/stack.sh {start|stop|restart|status}` (logs in `.run/logs/`). ## API - `GET /health` - `GET /api/search?q=` - `GET /api/market/indices` - `GET /api/tickers/{symbol}/overview` - `GET /api/tickers/{symbol}/history?period=1m|3m|6m|1y|5y` - `GET|POST|DELETE /api/watchlist[/{symbol}]` (uppercase, capped at 10) SQLite lives at `backend/data/prism.db`. Backend seeds a `default` profile on startup. ## Production Deployment Target topology: backend on `127.0.0.1:8001`, frontend on `127.0.0.1:3001`, nginx terminates TLS and reverse-proxies. Code lives at `/var/www/prism-v2/` owned by `www-data`. ### 1. Initial install ```bash sudo mkdir -p /var/www && sudo chown www-data:www-data /var/www sudo -u www-data git clone /var/www/prism-v2 cd /var/www/prism-v2 # Backend sudo -u www-data python3 -m venv backend/.venv sudo -u www-data backend/.venv/bin/pip install -r backend/requirements.txt # Frontend (writable npm cache required for www-data) sudo mkdir -p frontend/.npm && sudo chown -R www-data:www-data frontend sudo -u www-data env HOME=/var/www/prism-v2/frontend NPM_CONFIG_CACHE=/var/www/prism-v2/frontend/.npm \ npm --prefix frontend ci sudo -u www-data env HOME=/var/www/prism-v2/frontend NPM_CONFIG_CACHE=/var/www/prism-v2/frontend/.npm \ npm --prefix frontend run build ``` ### 2. systemd ```bash sudo cp systemd/prismv2-backend.service systemd/prismv2-frontend.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now prismv2-backend.service prismv2-frontend.service ``` ### 3. nginx + TLS ```bash sudo cp nginx/prism.tylerhoang.xyz.conf /etc/nginx/sites-available/prism.tylerhoang.xyz sudo ln -sf /etc/nginx/sites-available/prism.tylerhoang.xyz /etc/nginx/sites-enabled/ sudo certbot --nginx -d prism.tylerhoang.xyz # first time only sudo nginx -t && sudo systemctl reload nginx ``` ### 4. Redeploy ```bash cd /var/www/prism-v2 sudo -u www-data git pull origin master sudo -u www-data backend/.venv/bin/pip install -r backend/requirements.txt sudo -u www-data env HOME=/var/www/prism-v2/frontend NPM_CONFIG_CACHE=/var/www/prism-v2/frontend/.npm \ npm --prefix frontend ci sudo -u www-data env HOME=/var/www/prism-v2/frontend NPM_CONFIG_CACHE=/var/www/prism-v2/frontend/.npm \ npm --prefix frontend run build sudo systemctl restart prismv2-backend.service prismv2-frontend.service ``` ### Ops ```bash sudo systemctl status prismv2-backend.service prismv2-frontend.service --no-pager sudo journalctl -u prismv2-backend.service -f sudo journalctl -u prismv2-frontend.service -f curl -i http://127.0.0.1:8001/health curl -i https://prism.tylerhoang.xyz/api/search?q=AAPL ``` ## Verification ```bash pytest # backend tests (pytest.ini sets pythonpath) cd frontend && npm run lint && npm run build ``` ## Production Rules - Do not hardcode a localhost API base in frontend browser code. `frontend/lib/api.ts` must default to empty so the browser hits same-origin `/api/*`. - Never commit `.env`, `node_modules/`, `backend/.venv/`, or `backend/data/prism.db`. - Watchlist is normalized to uppercase and capped at 10 symbols.