Geopolitical and Macro Analyst for the upcoming big crisis of 2026 https://read.markets
Find a file
Giorgio Gilestro 70cf6148ce pricing: reflect what's actually shipped — add chat, tighten bullets
Audit against the live feature set surfaced one missing entry and a few
soft phrasings:

- Free now lists "Ask follow-up questions on any past log" — the /api/chat
  endpoint has no paid gate (router-level require_token only), so it's
  available to every signed-in user. The landing-page screenshot already
  showed it; the pricing page didn't mention it.

- "Per-group cross-asset summaries" → "Cross-asset indicator panels
  (equities, rates, FX, …) with a one-paragraph AI read on each tab" —
  more concrete about what the user actually sees.

- "Novice / Intermediate reading levels" → spelled out what each does
  (Novice defines jargon; Intermediate is terse).

- Free's exclusion list explicitly includes "Daily email digest" so the
  paid/free distinction reads cleanly without back-and-forth.

- Paid's daily-digest bullet now leads with the word count target
  (~600 words) so the value is concrete, not abstract.

- Encrypted cloud sync bullet now names the actual security model
  (PIN-derived in-browser + server-side outer wrap).

Added a small "Invite a friend" footnote — the credit ledger and invite
link both ship today; the rate kicks in with the payments rollout. Honest
phrasing keeps it from looking like vaporware.

Intro paragraph rewritten to lead with what's free (most of the editorial)
rather than what paid extends, since the free tier is the entry point.
2026-05-26 00:33:23 +02:00
alembic db: drop redundant user_id index on email_sends 2026-05-25 22:55:33 +02:00
app pricing: reflect what's actually shipped — add chat, tighten bullets 2026-05-26 00:33:23 +02:00
config add ECB Data Portal source; group-aware stale thresholds 2026-05-15 23:13:58 +01:00
docs/superpowers docs: implementation plan for beta + paid-gap rollout 2026-05-25 18:28:39 +02:00
tasks phase G: data minimisation + passwordless auth + DeepSeek-first LLM 2026-05-18 14:16:57 +01:00
tests test: drop stale "pie" assertion from test_default_groups_present 2026-05-26 00:20:01 +02:00
.dockerignore initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
.env.example initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
.gitignore initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
alembic.ini initial commit — cassandra v0.1 2026-05-15 21:56:10 +01:00
docker-compose.override.yml sync: encrypted cloud backup for portfolios + settings UX rework 2026-05-23 16:15:54 +02:00
docker-compose.prod.yml deploy: uvicorn --proxy-headers so https stays https behind NPM 2026-05-22 21:47:48 +01:00
docker-compose.test.yml test: standalone test container, isolated from the live prod stack 2026-05-25 23:58:55 +02:00
docker-compose.yml deploy: mount app/ + alembic from host in base compose 2026-05-25 12:49:27 +02:00
Dockerfile test+fix: make the suite run cleanly in the test container 2026-05-26 00:11:18 +02:00
pyproject.toml test: standalone test container, isolated from the live prod stack 2026-05-25 23:58:55 +02:00
README.md deploy: split compose into base (prod-ready) + dev override 2026-05-22 21:30:28 +01:00

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:

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 (local dev)

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/  # or whichever CASSANDRA_PORT you set

docker-compose.override.yml is auto-loaded and adds the host port binding so the app is reachable on localhost.

Production (VPS, NPM-fronted)

Always invoke with explicit -f flags — that way the dev override is skipped and the prod overlay (no host port, joins the external intranet Docker network, uvicorn on port 80) is applied:

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

Point Nginx Proxy Manager 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).