magnus 87bd53ca65
build / build (push) Failing after 7m22s
Verify repaired Gitea repository hooks
2026-09-15 17:41:50 +02:00
Fix
2026-09-10 13:01:11 +02:00
2026-09-10 13:12:35 +02:00
Fix
2026-09-10 13:01:11 +02:00
Fix
2026-09-10 13:01:11 +02:00

btcprice

Bitcoin price tracker UI. Serves an HTML page with live price updates streamed from btcdata, which this server proxies over WebSocket and renders as HTML fragments for HTMX.

Quick Start

# Start btcdata first (provides price data)
cd ../btcdata && make run

# Local dev — creates .venv and installs requirements on first run
make run       # starts on port 4000
make tailwind  # watch Tailwind CSS (separate terminal)

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.

Run the test suite with make test. Test-only packages are kept in requirements-dev.txt and are not installed in the production image.

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:

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.

CI images

Pushes to the main branch and tags matching v* run .gitea/workflows/build.yml. The workflow tests the application and publishes linux/amd64 images to harbor.pmagnus.cloud/btcprice/btcprice. Branch builds receive an immutable main-<UTC timestamp> tag (for Flux selection) and a SHA-qualified companion tag; release tags receive the version without v and a SHA-qualified companion tag. The image embeds the short Git SHA, available from /api/version.

The workflow requires the repository secrets HARBOR_ROBOT_USER and HARBOR_ROBOT_TOKEN. It only pushes images and intentionally has no Kubernetes credentials.

Legacy deployment (citadel)

./deploy-citadel.sh

Same method as ../elprice/deploy-citadel.sh: builds the image locally for the target's architecture (citadel is x86_64 → linux/amd64), copies docker-compose.citadel.yml and .env.citadel to /home/pmp/apps/btcprice on the host as docker-compose.yml / .env, pipes the image over SSH with docker save | docker load, and runs docker compose up -d --no-build. No registry involved.

Deployed btcprice listens on http://192.168.50.195:4041 and proxies to the btcdata running on citadel as well. Both attach to the external btc-network there, so BTCDATA_URL is http://btcdata:4102 (set in .env.citadel) — the service name inside the network, not a LAN address. The deploy script creates btc-network on the host if it does not exist yet.

Overridable: BTCPRICE_DEPLOY_HOST, BTCPRICE_DEPLOY_DIR, BTCPRICE_IMAGE_NAME, BTCPRICE_PLATFORM, BTCPRICE_NETWORK.

Environment Variables

Variable Default Description
BTCDATA_URL http://localhost:4100 btcdata service URL the server proxies to
APP_VERSION development Build identifier returned by /api/version
BTCDATA_LOCAL_URL — Used by make run-local instead of BTCDATA_URL
DOCKER_BTCDATA_PORT 4102 btcdata's port inside btc-network (local compose only)
BTCPRICE_PORT 4041 Host port in the citadel deployment (.env.citadel)

The HTTP port is not configurable via environment: make run hardcodes 4000 and the Docker image's CMD hardcodes 4040.

Health endpoints

  • /api/health is a process-only liveness check and remains healthy during a btcdata outage.
  • /api/ready checks ${BTCDATA_URL}/api/health with a three-second timeout and returns 503 when btcdata is unavailable.
  • /api/version returns the build SHA embedded by CI.

How It Works

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

Python · FastAPI · Uvicorn · websockets · HTMX · Tailwind CSS v4

The Clojure implementation this replaced is on the clojure branch.

S
Description
Bitcoin price tracker UI — WebSocket-based BTC price display
Readme
290 KiB
Languages
Python 65.4%
CSS 26%
Shell 3.7%
Makefile 2.7%
Dockerfile 1.9%
Other 0.3%