From 66acc6f7d18c93f4b7960682bea5bd5ff1545802 Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Sat, 30 May 2026 00:16:53 -0700 Subject: docs: tighten README, AGENTS, CLAUDE with production deploy instructions Co-Authored-By: Claude Opus 4.7 --- README.md | 239 ++++++++++++++++++-------------------------------------------- 1 file changed, 70 insertions(+), 169 deletions(-) (limited to 'README.md') diff --git a/README.md b/README.md index fb492f8..9e7f689 100644 --- a/README.md +++ b/README.md @@ -1,226 +1,127 @@ # 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 +Financial overview app. FastAPI backend (yfinance + SQLite watchlist) and Next.js frontend (Plotly chart, ticker search, market bar, watchlist). -## Environment +## Stack -Copy `.env.example` to `.env` if you want to set optional keys. +- Backend: Python 3.14+, FastAPI, uvicorn, yfinance, SQLite +- Frontend: Node 20+, Next.js (App Router), TypeScript +- Production: systemd + nginx (TLS via certbot) -Supported variable names are unchanged from Prism v1: +## Layout -- `FMP_API_KEY` -- `FINNHUB_API_KEY` -- `NEXT_PUBLIC_API_BASE_URL` +- `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/`) -The current Overview slice works without FMP or Finnhub keys because it relies on yfinance for the active endpoints. +## Environment -## Backend Setup +Copy `.env.example` → `.env`. Current feature set works without keys. -```bash -cd backend -python -m venv .venv -source .venv/bin/activate -pip install -r requirements.txt -``` +- `NEXT_PUBLIC_API_BASE_URL` — leave empty in production (same-origin `/api/*` via nginx) +- `FMP_API_KEY`, `FINNHUB_API_KEY` — reserved for future enrichment -Run the API: +## 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 ``` -Primary endpoints: +Or use `./scripts/stack.sh {start|stop|restart|status}` (logs in `.run/logs/`). + +## API - `GET /health` -- `GET /api/search?q=...` +- `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 -``` +- `GET|POST|DELETE /api/watchlist[/{symbol}]` (uppercase, capped at 10) -Run the frontend against the local backend: +SQLite lives at `backend/data/prism.db`. Backend seeds a `default` profile on startup. -```bash -NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8001 npm run dev -- --hostname 127.0.0.1 --port 3001 -``` +## Production Deployment -The UI stores the selected ticker in the URL, for example `/?ticker=AAPL`. +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`. -Production frontend runtime: +### 1. Initial install ```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 +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 -`scripts/stack.sh` manages both services as a local development stack: +# Backend +sudo -u www-data python3 -m venv backend/.venv +sudo -u www-data backend/.venv/bin/pip install -r backend/requirements.txt -```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 +# 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 ``` -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: +### 2. systemd ```bash -sudo cp systemd/prismv2-backend.service /etc/systemd/system/ -sudo cp systemd/prismv2-frontend.service /etc/systemd/system/ +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 ``` -Install nginx site: +### 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/prism.tylerhoang.xyz -sudo nginx -t -sudo systemctl reload nginx +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 ``` -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: +### 4. Redeploy ```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 -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 -sudo systemctl reload nginx ``` -## Verification - -Backend: +### Ops ```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: +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 -```bash -cd frontend -npm run lint -npm run build +curl -i http://127.0.0.1:8001/health +curl -i https://prism.tylerhoang.xyz/api/search?q=AAPL ``` -Production smoke checks: +## Verification ```bash -curl -i http://127.0.0.1:8001/health -curl -i "https://prism.tylerhoang.xyz/api/search?q=AAPL" +pytest # backend tests (pytest.ini sets pythonpath) +cd frontend && npm run lint && npm run build ``` -## 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` +## Production Rules -Those are the ports used by the current local bootstrap. +- 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. -- cgit v1.3-2-g0d8e