# Prism v2 Prism v2 is a monorepo rewrite of Prism's Overview experience with a FastAPI backend and a Next.js frontend. This first slice covers: - ticker search - selected ticker profile and quote - market bar - historical price chart - overview signal and stat cards - persisted watchlist backed by SQLite The implementation copies and adapts finance logic from Prism v1 into `backend/`; it does not import code from the old repo at runtime. ## Repo Layout - `backend/` - `app/main.py` FastAPI application and routes - `app/services/data_service.py` yfinance-backed Overview service layer with TTL caching - `app/db/watchlist.py` SQLite persistence for the default local profile - `data/prism.db` local watchlist database - `tests/` backend unit and API smoke tests - `frontend/` - `app/page.tsx` Overview shell - `components/PriceChart.tsx` Plotly price chart - `lib/api.ts` typed REST client - `types/api.ts` shared frontend response types - `scripts/stack.sh` unified start/stop/restart/status script - `systemd/` systemd unit files for running as a system service - `nginx/` nginx server block config (proxies `/api/` to backend, `/` to frontend) - `.env.example` optional environment variables - `pytest.ini` backend pytest import path config ## Requirements - Python 3.14+ - Node.js 20+ - npm ## Environment Copy `.env.example` to `.env` if you want to set optional keys. Supported variable names are unchanged from Prism v1: - `FMP_API_KEY` - `FINNHUB_API_KEY` - `NEXT_PUBLIC_API_BASE_URL` The current Overview slice works without FMP or Finnhub keys because it relies on yfinance for the active endpoints. ## Backend Setup ```bash cd backend python -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` Run the API: ```bash .venv/bin/uvicorn app.main:app --reload --host 127.0.0.1 --port 8001 ``` Primary endpoints: - `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 /api/watchlist` - `POST /api/watchlist/{symbol}` - `DELETE /api/watchlist/{symbol}` Notes: - SQLite lives at `backend/data/prism.db` - the backend seeds one `default` profile automatically - watchlist symbols are normalized to uppercase - watchlist size is capped at 10 symbols ## Frontend Setup ```bash cd frontend npm install ``` Run the frontend against the local backend: ```bash NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8001 npm run dev -- --hostname 127.0.0.1 --port 3001 ``` The UI stores the selected ticker in the URL, for example `/?ticker=AAPL`. Production frontend runtime: ```bash npm run build npm run start -- --hostname 127.0.0.1 --port 3001 ``` Important API-base rule: - In production, browser requests should use same-origin `/api/*` through nginx. - Do not hardcode a localhost fallback API base in frontend browser code. - `frontend/lib/api.ts` should default to an empty base when `NEXT_PUBLIC_API_BASE_URL` is unset. ## Quick Start `scripts/stack.sh` manages both services as a local development stack: ```bash ./scripts/stack.sh start # start backend + frontend in background ./scripts/stack.sh stop # stop both ./scripts/stack.sh restart # stop then start ./scripts/stack.sh status # show running PIDs and URLs ``` Notes: - expects `backend/.venv` and `frontend/node_modules` to already exist - default ports are backend `8001` and frontend `3001` - logs are written to `.run/logs/` - override hosts/ports via env vars: `BACKEND_HOST`, `BACKEND_PORT`, `FRONTEND_HOST`, `FRONTEND_PORT` ## Running in Production (systemd + nginx) The production model is: - backend on `127.0.0.1:8001` via `uvicorn` - frontend on `127.0.0.1:3001` via `next start` (not `next dev`) - nginx TLS reverse proxy: - `/api/*` -> backend - `/` -> frontend Unit templates live in `systemd/` and nginx server block template lives in `nginx/`. Install system services: ```bash sudo cp systemd/prismv2-backend.service /etc/systemd/system/ sudo cp systemd/prismv2-frontend.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now prismv2-backend.service prismv2-frontend.service ``` Install nginx site: ```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/prism.tylerhoang.xyz sudo nginx -t sudo systemctl reload nginx ``` Create writable npm cache for service user: ```bash sudo mkdir -p /var/www/prism-v2/frontend/.npm sudo chown -R www-data:www-data /var/www/prism-v2/frontend ``` Service controls: ```bash sudo systemctl status prismv2-backend.service --no-pager sudo systemctl status prismv2-frontend.service --no-pager sudo systemctl restart prismv2-backend.service prismv2-frontend.service sudo journalctl -u prismv2-backend.service -f sudo journalctl -u prismv2-frontend.service -f ``` Production deploy refresh: ```bash cd /var/www/prism-v2 git pull origin master cd backend python3 -m venv .venv .venv/bin/pip install -r requirements.txt cd ../frontend npm ci npm run build sudo systemctl restart prismv2-backend.service prismv2-frontend.service sudo systemctl reload nginx ``` ## Verification Backend: ```bash backend/.venv/bin/python -m py_compile backend/app/main.py backend/app/schemas.py backend/app/services/data_service.py backend/app/db/watchlist.py backend/.venv/bin/python -m pytest backend/tests ``` Frontend: ```bash cd frontend npm run lint npm run build ``` Production smoke checks: ```bash curl -i http://127.0.0.1:8001/health curl -i "https://prism.tylerhoang.xyz/api/search?q=AAPL" ``` ## Current Local URLs If port `8000` is already occupied on your machine, use: - backend: `http://127.0.0.1:8001` - frontend: `http://127.0.0.1:3001` Those are the ports used by the current local bootstrap.