Update doc
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
# Copy to .env and fill in. .env is gitignored.
|
||||||
|
# The Makefile does `include .env`, so this file must exist before `make run`.
|
||||||
|
|
||||||
|
# --- Local dev (make run) ---
|
||||||
|
# btcdata instance the server proxies WebSockets to. The code falls back to
|
||||||
|
# http://localhost:4100 when unset, but the Makefile needs the file to exist.
|
||||||
|
BTCDATA_URL=http://localhost:4100
|
||||||
|
|
||||||
|
# Used by `make run-local` to point at a btcdata on this machine while
|
||||||
|
# BTCDATA_URL above points elsewhere (e.g. a deployed instance).
|
||||||
|
BTCDATA_LOCAL_URL=http://localhost:4100
|
||||||
|
|
||||||
|
# --- Docker (docker compose up -d) ---
|
||||||
|
# Port btcdata listens on inside btc-network. Must match DOCKER_BTCDATA_PORT
|
||||||
|
# in ../btcdata/.env.
|
||||||
|
DOCKER_BTCDATA_PORT=4102
|
||||||
@@ -1,39 +1,54 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
Bitcoin price tracker UI — Python FastAPI web application. Serves the HTML/Tailwind UI and
|
||||||
|
proxies live price data from btcdata over WebSocket.
|
||||||
## 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
|
## Build & Development Commands
|
||||||
|
|
||||||
- `make run` — Start dev server on port 4000 (connects to btcdata at BTCDATA_URL from `.env`)
|
- `make run` — Start dev server on port 4000; creates `.venv` and installs `requirements.txt`
|
||||||
- `make run-local` — Start dev server using BTCDATA_LOCAL_URL from `.env`
|
on first run (the `venv` target, keyed off `requirements.txt`)
|
||||||
- `make tailwind` — Watch Tailwind CSS for changes (run in separate terminal)
|
- `cp .env.example .env` — optional; `.env` is `-include`d, so a missing one is not fatal
|
||||||
- `make test` — Run tests with pytest (`tests/` directory)
|
- `make run-local` — Same, but with `BTCDATA_URL=$BTCDATA_LOCAL_URL`
|
||||||
- `npm run css:build` — One-off Tailwind CSS build
|
- `make tailwind` — Watch Tailwind CSS for changes
|
||||||
|
- `make test` — Runs `pytest tests/`, but there is no `tests/` directory yet and pytest is not
|
||||||
|
in `requirements.txt`
|
||||||
|
- `make venv` — Bootstrap the virtualenv without starting the server
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
Docker runs alongside local dev on different ports:
|
Docker runs alongside local dev on different ports:
|
||||||
|
|
||||||
| Service | Local dev | Docker |
|
| Service | Local dev | Docker |
|
||||||
|----------|----------------|----------------|
|
|----------|----------------|--------------------------------------|
|
||||||
| btcprice | localhost:4000 | localhost:4041 |
|
| btcprice | localhost:4000 | localhost:4041 (container port 4040) |
|
||||||
| btcdata | localhost:4100 | localhost:4101 |
|
| btcdata | localhost:4100 | localhost:4102 |
|
||||||
|
|
||||||
Uses external `btc-network` Docker network. btcdata must be running separately (or via its own docker-compose).
|
`docker compose up -d` here starts **btcprice only**. Both projects attach to the external
|
||||||
|
`btc-network` (`docker network create btc-network` once), and btcdata must be started from
|
||||||
|
`../btcdata`. Inside the network btcprice reaches it at `http://btcdata:${DOCKER_BTCDATA_PORT:-4102}`.
|
||||||
|
|
||||||
|
Note: `Dockerfile` bakes in a stale `ENV BTCDATA_URL=http://btcdata:4101`; compose always
|
||||||
|
overrides it, so it only matters if the image is run outside compose. `ENV PORT` is likewise
|
||||||
|
unused — the port in `CMD` is hardcoded.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
- **Framework:** FastAPI + Uvicorn
|
- **Framework:** FastAPI
|
||||||
- **Templates:** Inline HTML strings in Python + HTMX (WebSocket extension)
|
- **Server:** Uvicorn
|
||||||
- **Styling:** Tailwind CSS v4 — scans `app/**/*.py` for class names (configured in `resources/css/input.css` via `@source`)
|
- **Templates:** Inline HTML strings + HTMX (WebSocket extension)
|
||||||
- **Data backend:** btcdata (separate service at BTCDATA_URL, default http://localhost:4100)
|
- **Styling:** Tailwind CSS v4
|
||||||
|
- **Data backend:** btcdata (separate service at `BTCDATA_URL`, default `http://localhost:4100`)
|
||||||
- **No database** — all data comes from btcdata
|
- **No database** — all data comes from btcdata
|
||||||
|
|
||||||
### Data Flow
|
### btcdata connection
|
||||||
|
|
||||||
|
The browser connects only to btcprice: `ws-connect="/ws/price"` and `ws-connect="/ws/strike"`.
|
||||||
|
Each endpoint runs `_ws_proxy`, which opens an upstream WebSocket to btcdata's `/api/price/ws`
|
||||||
|
and `/api/strike/ws`, converts each JSON message to an HTML fragment (`price_json_to_html`,
|
||||||
|
`strike_json_to_html`) and forwards it. `BTCDATA_URL` is the single point of contact;
|
||||||
|
`_btcdata_ws_url` rewrites its scheme to `ws`/`wss`.
|
||||||
|
|
||||||
|
## Source Layout
|
||||||
|
|
||||||
btcprice acts as a WebSocket proxy between the browser and btcdata:
|
btcprice acts as a WebSocket proxy between the browser and btcdata:
|
||||||
1. Browser connects via HTMX WebSocket to `/ws/price` or `/ws/strike`
|
1. Browser connects via HTMX WebSocket to `/ws/price` or `/ws/strike`
|
||||||
|
|||||||
@@ -1,19 +1,29 @@
|
|||||||
include .env
|
-include .env
|
||||||
export
|
export
|
||||||
|
|
||||||
.PHONY: clean run run-docker tailwind test
|
VENV := .venv
|
||||||
|
UVICORN := $(VENV)/bin/uvicorn
|
||||||
|
|
||||||
|
.PHONY: clean run run-local tailwind test venv
|
||||||
|
|
||||||
|
venv: $(UVICORN)
|
||||||
|
|
||||||
|
$(UVICORN): requirements.txt
|
||||||
|
python3 -m venv $(VENV)
|
||||||
|
$(VENV)/bin/pip install --upgrade pip
|
||||||
|
$(VENV)/bin/pip install -r requirements.txt
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf __pycache__ app/__pycache__
|
rm -rf __pycache__ app/__pycache__
|
||||||
|
|
||||||
run:
|
run: venv
|
||||||
.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 4000 --reload
|
$(UVICORN) app.main:app --host 0.0.0.0 --port 4000 --reload
|
||||||
|
|
||||||
run-local:
|
run-local: venv
|
||||||
BTCDATA_URL=$(BTCDATA_LOCAL_URL) .venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 4000 --reload
|
BTCDATA_URL=$(BTCDATA_LOCAL_URL) $(UVICORN) app.main:app --host 0.0.0.0 --port 4000 --reload
|
||||||
|
|
||||||
tailwind:
|
tailwind:
|
||||||
npm run css:watch
|
npm run css:watch
|
||||||
|
|
||||||
test:
|
test: venv
|
||||||
.venv/bin/python -m pytest tests/
|
$(VENV)/bin/python -m pytest tests/
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# btcprice
|
# btcprice
|
||||||
|
|
||||||
Bitcoin price tracker UI. Serves an HTML page with live price updates streamed from [btcdata](../btcdata) via WebSocket using HTMX.
|
Bitcoin price tracker UI. Serves an HTML page with live price updates streamed from
|
||||||
|
[btcdata](../btcdata), which this server proxies over WebSocket and renders as HTML fragments
|
||||||
|
for HTMX.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -8,25 +10,57 @@ Bitcoin price tracker UI. Serves an HTML page with live price updates streamed f
|
|||||||
# Start btcdata first (provides price data)
|
# Start btcdata first (provides price data)
|
||||||
cd ../btcdata && make run
|
cd ../btcdata && make run
|
||||||
|
|
||||||
# Local dev
|
# Local dev — creates .venv and installs requirements on first run
|
||||||
make run # starts on port 4000
|
make run # starts on port 4000
|
||||||
make tailwind # watch Tailwind CSS (separate terminal)
|
make tailwind # watch Tailwind CSS (separate terminal)
|
||||||
|
|
||||||
# Docker (starts both btcprice + btcdata)
|
|
||||||
docker compose up -d # btcprice on 4041, btcdata on 4101
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Optionally `cp .env.example .env` to override `BTCDATA_URL`; without it the code default
|
||||||
|
(`http://localhost:4100`) applies. `make run-local` requires a `.env` defining
|
||||||
|
`BTCDATA_LOCAL_URL`.
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
`docker compose up -d` starts **btcprice only** — it does not bring up btcdata. Both compose
|
||||||
|
files attach to the external `btc-network`, so create it once and start btcdata separately:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network create btc-network # once
|
||||||
|
cd ../btcdata && docker compose up -d
|
||||||
|
cd ../btcprice && docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
| Service | Local dev | Docker |
|
||||||
|
|----------|----------------|---------------------------------------|
|
||||||
|
| btcprice | localhost:4000 | localhost:4041 (container port 4040) |
|
||||||
|
| btcdata | localhost:4100 | localhost:4102 |
|
||||||
|
|
||||||
|
Inside `btc-network`, btcprice reaches btcdata as `http://btcdata:4102`.
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `PORT` | `4000` | HTTP server port |
|
| `BTCDATA_URL` | `http://localhost:4100` | btcdata service URL the server proxies to |
|
||||||
| `BTCDATA_URL` | `http://192.168.50.42:4100` | btcdata service URL (browser connects via WebSocket) |
|
| `BTCDATA_LOCAL_URL` | — | Used by `make run-local` instead of `BTCDATA_URL` |
|
||||||
|
| `DOCKER_BTCDATA_PORT` | `4102` | btcdata's port inside `btc-network` (compose only) |
|
||||||
|
|
||||||
|
The HTTP port is not configurable via environment: `make run` hardcodes 4000 and the Docker
|
||||||
|
image's `CMD` hardcodes 4040.
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
The server renders an HTML page with HTMX and the WebSocket extension (`hx-ext="ws"`). HTMX connects directly to btcdata's WebSocket endpoint (`BTCDATA_URL/api/price/ws`), which sends HTML fragments. HTMX swaps the received `<div id="price-display">` into the DOM automatically. Price changes are color-coded (green up, red down). Reconnection is handled by HTMX with exponential backoff.
|
The browser loads a page with HTMX and the WebSocket extension, which connects back to
|
||||||
|
**btcprice** at `/ws/price` and `/ws/strike` — the browser never contacts btcdata directly.
|
||||||
|
|
||||||
|
Each of those endpoints opens an upstream WebSocket to btcdata (`/api/price/ws` and
|
||||||
|
`/api/strike/ws`), converts each JSON message to an HTML fragment (`price_json_to_html`,
|
||||||
|
`strike_json_to_html`), and forwards it to the browser. HTMX swaps the received
|
||||||
|
`<div id="price-display">` / `<div id="strike-display">` into the DOM. Price changes are
|
||||||
|
color-coded (green up, red down). Reconnection is handled by HTMX.
|
||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
Clojure · Kit · Undertow · Reitit · Hiccup · HTMX · Tailwind CSS v4
|
Python · FastAPI · Uvicorn · websockets · HTMX · Tailwind CSS v4
|
||||||
|
|
||||||
|
The Clojure implementation this replaced is on the `clojure` branch.
|
||||||
|
|||||||
Reference in New Issue
Block a user