diff --git a/.gitignore b/.gitignore index 9c3b474..f7014ed 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __pycache__/ *.log /.env /token +/=0.27 diff --git a/CLAUDE.md b/CLAUDE.md index 66e9502..c31038c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,12 +1,18 @@ -# btcprice +# CLAUDE.md -Bitcoin price tracker UI — Python FastAPI web application. Serves the HTML/Tailwind UI. Connects to btcdata for live price data via WebSocket. +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +Bitcoin price tracker UI — Python FastAPI web application. Serves an HTML/Tailwind page with live price updates streamed from btcdata (separate service) via WebSocket using HTMX. ## Build & Development Commands -- `make run` — Start dev server on port 4000 -- `make tailwind` — Watch Tailwind CSS for changes -- `make test` — Run tests +- `make run` — Start dev server on port 4000 (connects to btcdata at BTCDATA_URL from `.env`) +- `make run-local` — Start dev server using BTCDATA_LOCAL_URL from `.env` +- `make tailwind` — Watch Tailwind CSS for changes (run in separate terminal) +- `make test` — Run tests with pytest (`tests/` directory) +- `npm run css:build` — One-off Tailwind CSS build ## Docker @@ -17,20 +23,26 @@ Docker runs alongside local dev on different ports: | btcprice | localhost:4000 | localhost:4041 | | btcdata | localhost:4100 | localhost:4101 | -btcprice's docker-compose includes btcdata via `include: ../btcdata/docker-compose.yml`. +Uses external `btc-network` Docker network. btcdata must be running separately (or via its own docker-compose). ## Architecture -- **Framework:** FastAPI -- **Server:** Uvicorn -- **Templates:** Inline HTML strings + HTMX (WebSocket extension) -- **Styling:** Tailwind CSS v4 +- **Framework:** FastAPI + Uvicorn +- **Templates:** Inline HTML strings in Python + HTMX (WebSocket extension) +- **Styling:** Tailwind CSS v4 — scans `app/**/*.py` for class names (configured in `resources/css/input.css` via `@source`) - **Data backend:** btcdata (separate service at BTCDATA_URL, default http://localhost:4100) - **No database** — all data comes from btcdata -## Source Layout +### Data Flow -``` -app/ -└── main.py # FastAPI app: routes, WebSocket proxy, HTML rendering -``` +btcprice acts as a WebSocket proxy between the browser and btcdata: +1. Browser connects via HTMX WebSocket to `/ws/price` or `/ws/strike` +2. btcprice proxies to btcdata's `/api/price/ws` or `/api/strike/ws` +3. JSON from btcdata is transformed into HTML fragments (in `price_json_to_html` / `strike_json_to_html`) +4. HTMX swaps the HTML into the DOM by matching element IDs (`price-display`, `strike-display`) + +### Key Conventions + +- Numbers use Danish locale formatting (dots for thousands, commas for decimals) via `da_fmt()` +- Price changes are color-coded: green (up), red (down), gray (unchanged) +- All HTML is built as string concatenation in Python — no template engine diff --git a/app/main.py b/app/main.py index e19b9bf..7db4191 100644 --- a/app/main.py +++ b/app/main.py @@ -3,9 +3,10 @@ import logging import os from datetime import datetime +import httpx import websockets from fastapi import FastAPI, WebSocket, WebSocketDisconnect -from fastapi.responses import FileResponse, HTMLResponse +from fastapi.responses import FileResponse, HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles logging.basicConfig(level=logging.INFO) @@ -38,6 +39,7 @@ HOME_HTML = """\ +
1h Candles (1m)
+ +24h Candles (1h)
+ +