# chart FastAPI backend + Vue 3 (from CDN, no build step) served at . The app charts Yahoo's `ES=F` feed, builds CME-session-aware timeframes and daily moving averages, and alerts on confluence zones. The full spec lives in [`docs/IMPLEMENTATION_PLAN.md`](docs/IMPLEMENTATION_PLAN.md) — read it before writing code; it records decisions and verified API facts that are expensive to rediscover. ## Local development ```bash docker compose up --build ``` Then open . Override the host port with, for example, `PORT=8020 docker compose up`. The port binds to all host interfaces, so another machine can connect at `http://HOST_IP:8010`. The source tree is bind-mounted and uvicorn runs with `--reload`, so edits to `main.py` or `static/` take effect without a rebuild. Rebuild only when `requirements.txt` changes. Without Docker: ```bash python3 -m venv .venv && . .venv/bin/activate pip install -r requirements.txt uvicorn main:app --reload ``` Copy settings from `.env.example` as needed. To recalibrate the alert threshold against Yahoo's current eight-day minute tape: ```bash python3 -m scripts.calibrate_alerts ``` The M4 calibration on 2026-08-09 replayed 8,065 minute bars across seven sessions. Threshold `12` generated 210 alerts from lone daily MAs; `24` and the selected `28` generated none. The selected threshold deliberately requires at least three clustered daily MAs (score `36`) and should be revisited as more varied tapes are recorded. ## Layout | Path | Purpose | |---|---| | `main.py` | FastAPI lifespan and app wiring; JSON under `/api`, SPA at `/` | | `app/` | Market sources, aggregation, analysis, alerts, and API | | `static/` | `index.html`, `app.js`, `style.css` — Vue 3 loaded from unpkg | | `requirements.txt` | Python deps | | `Procfile` | Start command; **nixpacks needs this** or the deploy has nothing to run | | `Dockerfile.dev`, `docker-compose.yml` | Local dev only — production does not use them | ## Deployment Push to `main` → Forgejo webhook → Coolify rebuilds with nixpacks → live in roughly 25 seconds. ```bash git push ``` Two things to know before changing the deploy config: - The Coolify domain is registered as `https://chart.amow.com:8000`. The port suffix is how Coolify decides the Traefik target port; drop it and every request 502s while the container looks perfectly healthy. It does not appear in the public URL. - Ignore a 502 in the first minute after a deploy — that's the rolling container swap, and it clears on its own. Manual redeploy: ```bash curl -X POST -H "Authorization: Bearer $(cat ~/.coolify-token)" \ "http://127.0.0.1:8000/api/v1/deploy?uuid=dgvch0xqv8uvjfor7dl8bwl9&force=true" ```