3.6 KiB
Market Screener UI
SvelteKit 5 dashboard for the Market Screener API. Provides an interactive interface for screening stocks, ETFs, and bonds — and tracking your portfolio with live hold/sell/add advice.
Quick Start
This UI requires the Market Screener API running on port 3000.
# Recommended: start both from the API repo
cd ../market_screener
npm run dev # starts API (:3000) + this UI (:5173) together
# Or start the UI independently
npm install
npm run dev # http://localhost:5173
Pages
Screener (/)
- Enter any tickers (comma or space separated) and click Screen
- Click 📰 Catalysts to load today's news-driven tickers and screen them automatically (one click)
- Market context strip shows live benchmarks: 10Y yield, VIX, S&P 500, P/E ratios, rate regime
- Signal Summary table ranks all assets by signal strength
- Drill-down tables for Stocks, ETFs, and Bonds with Mkt-Adjusted / Graham tab toggle
- Ticker column stays pinned while scrolling wide tables
Portfolio (/portfolio)
- Reads
portfolio.jsonfrom the API server - Shows total value, cost basis, and unrealised G/L
- Per-holding advice: ✅ Hold & Add, 🟡 Reduce, 🔴 Sell
- If SimpleFIN is configured: net worth, account balances, 30-day spending breakdown
Signals Explained
| Signal | Meaning |
|---|---|
| ✅ Strong Buy | Passes both Market-Adjusted AND Fundamental gates |
| ⚡ Momentum | Passes market-adjusted, holds fundamentally |
| ⚠️ Speculation | Passes market-adjusted, fails fundamental — priced for perfection |
| 🔄 Neutral | Hold territory in one or both lenses |
| ❌ Avoid | Fails both gates |
The Mkt-Adjusted tab uses gates derived from live market data (e.g. S&P P/E × 1.5 for the P/E gate). The Graham tab uses strict historical value-investing gates (P/E < 15×, PEG < 1.0).
Tech Stack
| Layer | Choice |
|---|---|
| Framework | SvelteKit 2 + Svelte 5 |
| Build tool | Vite 6 |
| Adapter | @sveltejs/adapter-auto |
| Rendering | Client-side only (SSR disabled) |
| API | Proxied via Vite dev server → Fastify on :3000 |
Project Structure
src/
app.html HTML shell
app.css Global reset + dark theme base
routes/
+layout.js ssr = false
+layout.svelte Nav bar
+page.svelte Screener page
portfolio/
+page.js load() → fetches /api/finance/portfolio
+page.svelte Portfolio + SimpleFIN page
lib/
api.js All API fetch functions
SignalBadge.svelte Signal pill component
MarketContext.svelte Benchmark strip component
vite.config.js /api proxy → localhost:3000
svelte.config.js SvelteKit config
Configuration
API URL
In vite.config.js, the Vite dev server proxies /api/* to http://localhost:3000. To point at a different API host, update the proxy target there.
For production, configure your reverse proxy (nginx, Caddy, etc.) to route /api/* to the Fastify server.
CORS
The Fastify API allows http://localhost:5173 by default. If you deploy the UI to a different origin, set CLIENT_ORIGIN in the API's .env:
CLIENT_ORIGIN=https://your-deployed-ui.example.com
Development Notes
- Uses Svelte 5 runes:
$state,$derived,$derived.by,$props onclick={handler}noton:click— Svelte 5 syntax- Page data loaded via
+page.jsload()function, notonMount - Global CSS lives in
src/app.css— no:global()in component<style>blocks asset.displayMetrics(plain object from API) — never callgetDisplayMetrics()in the browser