kaykayyali d7028ab190
Some checks failed
build / Build & Push & Dispatch (push) Failing after 25m46s
Merge pull request 'refactor/component-tree-2' (#3) from refactor/component-tree-2 into master
Reviewed-on: #3
2026-06-24 01:07:54 +00:00

WH40K Points Comparator

Compare Warhammer 40,000 unit points across Munitorum Field Manual versions.

Features

  • Multi-version comparison — Track points changes across 5 MFM versions (1.14 → current)
  • Faction filtering — Browse by faction or view all 1,449 units
  • Biggest movers — Top 5 price drops and rises for the current view
  • Historical graph — Click any unit to see a points history chart across all MFM versions
  • Shareable URLs — Filter state is stored in URL query params (?faction=...&dir=...&q=...)
  • Mobile responsive — Flex-based layout that scales to any device
  • Social embeds — OG/Twitter meta tags with grimdark favicon and preview image

Tech Stack

  • React + MUI (Material UI DataGrid)
  • Vite build
  • nginx (Alpine) in Docker
  • Traefik reverse proxy with Cloudflare TLS

Data Sources

  • Current MFM — Scraped from warhammer-community.com (live data)
  • MFM 4.3 (Jun 2026), 3.2 (Aug 2025), 2.3 (Mar 2025), 1.14 (Dec 2024) — Parsed from PDFs

Deployment

  1. Edit docker-compose.yml — change the Host() rule to your domain
  2. Build and deploy:
docker compose up -d --build

Without Traefik

Uncomment the ports section in docker-compose.yml:

ports:
  - "8080:80"

Then access at http://localhost:8080.

Building from scratch

The Dockerfile is multi-stage:

  1. Build stagenode:20-alpine installs deps and runs npm run build
  2. Runtime stagenginx:alpine serves the static files

No pre-built artifacts needed — just docker compose build.

Data Pipeline

PDFs + live scrape → per-faction JSON files
                         ↓
              build_deduped_data.py
                         ↓
              react-app/public/data.json
                         ↓
                   React app (fetched at runtime)

Run python3 build_deduped_data.py to rebuild data.json from source data.

Project Structure

wh40k-factions/
├── Dockerfile              # Multi-stage: node build → nginx serve
├── docker-compose.yml      # Traefik + Cloudflare TLS config
├── build_deduped_data.py   # Merges all MFM versions into data.json
├── parse_pdf_per_faction.py # PDF → per-faction JSON (MFM 4.3)
├── react-app/
│   ├── index.html          # OG meta tags, favicon
│   ├── package.json
│   ├── vite.config.js
│   ├── public/
│   │   ├── data.json       # Merged dataset (5 MFM versions)
│   │   ├── favicon.png     # Grimdark Aquila icon
│   │   └── og-image.png    # Social embed banner
│   └── src/
│       ├── main.jsx
│       └── App.jsx         # Main app: filters, movers, DataGrid, graph modal
├── live/                   # Current MFM scrape (per-faction JSON)
├── pdf/                    # MFM 4.3 PDF parse (per-faction JSON)
├── pdf32/                  # MFM 3.2 PDF parse
├── pdf23/                  # MFM 2.3 PDF parse
└── pdf114/                 # MFM 1.14 PDF parse

License

MIT

Description
WH40K Points Comparator — compare unit points across Munitorum Field Manual versions
Readme 2.3 MiB
Languages
Python 48.9%
JavaScript 38.2%
CSS 7.7%
HTML 4.1%
Dockerfile 1.1%