The VPS deployment sits behind Nginx Proxy Manager on a pre-existing `intranet` Docker bridge network. The overlay drops the host port binding from the base compose, switches uvicorn to listen on port 80 inside the container (uniform NPM upstreams), and joins the app to both `default` (for db/redis) and `intranet` (for NPM ingress). Apply with: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d Local dev (compose without the overlay) is unchanged — still binds the host port from CASSANDRA_PORT in .env. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55 lines
2.2 KiB
Markdown
55 lines
2.2 KiB
Markdown
# Read the Markets
|
|
|
|
Containerised macro-strategy dashboard — hourly market data, RSS news, Trading 212 portfolio, and an AI-generated strategic log written by **Cassandra**, the in-product seer. Read-only by design.
|
|
|
|
Production:
|
|
- Landing: <https://read.markets>
|
|
- App: <https://app.read.markets>
|
|
|
|
The Python package is still named `cassandra` and several internal identifiers (cookie names, advisory-lock keys, `CASSANDRA_TOKEN` env var, CSS filename) keep the legacy name on purpose — renaming them would invalidate live sessions / locks / configs for no user benefit. See `app/branding.py` for the brand single-source-of-truth.
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
cp .env.example .env # fill in API keys; set CASSANDRA_TOKEN if exposing
|
|
docker compose up --build # db + app + scheduler + daily backup sidecar
|
|
open http://localhost:8000/
|
|
```
|
|
|
|
## Production (VPS)
|
|
|
|
Apply the prod overlay so the app has no host port binding and joins the
|
|
existing `intranet` Docker network (where Nginx Proxy Manager lives):
|
|
|
|
```bash
|
|
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
|
|
```
|
|
|
|
Then point NPM at upstream `readmarkets-app-1:80`.
|
|
|
|
## Architecture
|
|
|
|
- **app** (FastAPI + Jinja2 + HTMX) — web dashboard on port 8000
|
|
- **scheduler** (APScheduler) — hourly ingestion jobs (market, news, portfolio, AI log)
|
|
- **db** (MariaDB 11) — quotes, headlines, portfolio snapshots, strategic logs, job runs
|
|
- **backup** (sidecar) — daily mariadb-dump to `./backup/`
|
|
|
|
See `/home/gg/.claude/plans/ok-i-think-this-tidy-lake.md` for the design plan.
|
|
|
|
## Config
|
|
|
|
| File | Purpose |
|
|
|---|---|
|
|
| `config/default.toml` | Universal data tables: indicator groups, RSS feeds, keyword presets |
|
|
| `config/portfolio.toml` | User-specific portfolios (overrides `default.toml`) |
|
|
| `.env` | Secrets and runtime knobs — mounted read-only into containers |
|
|
|
|
## Endpoints
|
|
|
|
- `GET /` — dashboard
|
|
- `GET /portfolio/{name}` — portfolio detail
|
|
- `GET /news` — news feed
|
|
- `GET /log` — strategic-log archive
|
|
- `GET /api/health` — job status (last success / failure per job)
|
|
|
|
All authenticated routes require `Authorization: Bearer $CASSANDRA_TOKEN` if the env is set; if unset, the app is open (LAN-only mode).
|