| .github | ||
| code | ||
| config | ||
| csv_files/testdata | ||
| docs | ||
| logs/perf | ||
| tests/e2e | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CONTRIBUTING_EDITORIAL.md | ||
| docker-compose.yml | ||
| DOCKER.md | ||
| Dockerfile | ||
| dockerhub-docker-compose.yml | ||
| entrypoint.sh | ||
| LICENSE | ||
| mtg_deckbuilder.spec | ||
| mypy.ini | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.js | ||
| pyproject.toml | ||
| pytest.ini | ||
| README.md | ||
| RELEASE_NOTES_TEMPLATE.md | ||
| requirements-dev.txt | ||
| requirements.txt | ||
| run-web-from-dockerhub.bat | ||
| run-web-from-dockerhub.sh | ||
| tailwind.config.js | ||
| tsconfig.json | ||
| tsconfig.tsbuildinfo | ||
🃏 MTG Python Deckbuilder
A web-first Commander/EDH deckbuilder with a shared core for CLI, headless, and Docker workflows. It builds curated decks, enforces bracket policies, understands owned cards, and ships a modern FastAPI + HTMX UI.
- Web UI priority: All homepage actions map to the sections below.
- Shared logic: Web, CLI, and headless runs use the same builder engine and exports.
- Deterministic outputs: Random modes respect seeds, include/exclude lists, and bracket rules.
- Data-aware UX: Owned library, themes, commanders, diagnostics, and logs live side-by-side.
Table of contents
- Quick start
- Homepage guide
- CLI & headless flows
- Data, exports, and volumes
- Environment variables
- Project layout
- Development setup
- Troubleshooting
- Contributing
- License & attribution
- Further reading
Quick start
Pick the path that fits your setup. All commands target Windows PowerShell.
Option 1 — Docker Compose (recommended web experience)
docker compose up --build --no-deps -d web
The Web UI starts on http://localhost:8080. First boot seeds data, refreshes decks, and tags cards automatically (see env defaults in docker-compose.yml). Use docker compose stop web / docker compose start web to pause or resume.
Option 2 — Docker Hub image
docker run --rm -p 8080:8080 `
-v "${PWD}/deck_files:/app/deck_files" `
-v "${PWD}/logs:/app/logs" `
-v "${PWD}/csv_files:/app/csv_files" `
-v "${PWD}/config:/app/config" `
-v "${PWD}/owned_cards:/app/owned_cards" `
mwisnowski/mtg-python-deckbuilder:latest
Brings up the same web UI using the prebuilt image. All volumes persist on the host.
Option 3 — Run from source
python -m venv .venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn code.web.app:app --host 127.0.0.1 --port 8080
CLI entry point: python code/main.py. Headless convenience runner: python code/headless_runner.py --config config/deck.json.
For deeper Docker notes (including headless runs, impersonating CLI via compose, and maintenance scripts) see DOCKER.md.
Homepage guide
Every tile on the homepage connects to a workflow. Use these sections as your tour.
Build a Deck
Start here for interactive deck creation.
- Pick commander, themes (primary/secondary/tertiary), bracket, and optional deck name in the unified modal.
- Build X and Compare (
ENABLE_BATCH_BUILD=1, default): Build 1-10 decks with the same configuration to see variance- Parallel execution (max 5 concurrent) with real-time progress and dynamic time estimates
- Comparison view shows card overlap statistics and individual build summaries
- Synergy Builder: Analyze builds and create optimized "best-of" deck scored by frequency, EDHREC rank, and theme tags
- Rebuild button for quick iterations, ZIP export for all builds
- See
docs/user_guides/batch_build_compare.mdfor full guide
- Quick Build: One-click automation runs the full workflow with live progress (Creatures → Spells → Lands → Final Touches → Summary). Available in New Deck wizard.
- Skip Controls: Granular stage-skipping toggles in New Deck wizard (21 flags: land steps, creature stages, spell categories). Auto-advance without approval prompts.
- Add supplemental themes in the Additional Themes section (ENABLE_CUSTOM_THEMES): fuzzy suggestions, removable chips, and strict/permissive matching toggles respect
THEME_MATCH_MODEandUSER_THEME_LIMIT. - Partner mechanics (ENABLE_PARTNER_MECHANICS): Step 2 and the quick-start modal auto-enable partner controls for eligible commanders, show only legal partner/background/Doctor options, and keep previews, warnings, and theme chips in sync.
- Partner suggestions (ENABLE_PARTNER_SUGGESTIONS): ranked chips appear beside the partner selector, recommending popular partner/background/Doctor pairings based on the analytics dataset; selections respect existing partner mode and lock states.
- Partner: pick a second commander from the filtered dropdown labeled “Partner commander”; the background picker clears automatically.
- Partner With: the canonical partner pre-fills and surfaces an opt-out chip so you can keep or swap the suggestion.
- Doctor / Doctor’s Companion: Doctors list legal companions (and vice versa) with role labels, and the opt-out chip mirrors Partner With behavior.
- Background: choose a Background instead of a second commander; partner selectors hide when not applicable.
- Locks, Replace, Compare, and Permalinks live in Step 5.
- Exports (CSV, TXT, compliance JSON, summary JSON) land in
deck_files/and reuse your chosen deck name when set. CSV/TXT headers now include commander metadata (names, partner mode, colors) so downstream tools can pick up dual-commander context without extra parsing. ALLOW_MUST_HAVES=1(default) enables include/exclude enforcement.WEB_AUTO_ENFORCE=1re-runs bracket enforcement automatically after each build.WEB_STAGE_ORDER=new(default) runs creatures/spells before lands for better pip analysis. Uselegacyfor original lands-first order.WEB_IDEALS_UI=slider(default) shows interactive range sliders for ideal counts with live validation. Useinputfor traditional text boxes.
Run a JSON Config
Execute saved configs without manual input.
- Place JSON configs under
config/(seeconfig/deck.jsonfor a template). - Launch via homepage button or by running the container with
APP_MODE=cliandDECK_MODE=headless. - Respect include/exclude, owned, and theme overrides defined in the config file or env vars.
- Supplemental themes: add
"additional_themes": ["Theme A", "Theme B"]plus"theme_match_mode": "permissive"|"strict". Strict mode stops the build when a theme cannot be resolved; permissive keeps going and prints suggestions. Exported configs also include a camelCase alias ("userThemes") and the active catalog version ("themeCatalogVersion"); either field name is accepted on import.
Initial Setup
Refresh data and caches when formats shift.
- First run: Auto-downloads pre-tagged card database from GitHub (instant setup)
- Manual refresh: Download button in web UI or run setup locally
- Runs card downloads, data generation, smart tagging (keywords + protection grants), and commander catalog rebuilds
- Controlled by
SHOW_SETUP=1(on by default in compose) - Force a full rebuild (setup + tagging):
# Docker: docker compose run --rm web python -c "from code.file_setup.setup import initial_setup; from code.tagging.tagger import run_tagging; initial_setup(); run_tagging()" # Local (with venv activated): python -c "from code.file_setup.setup import initial_setup; from code.tagging.tagger import run_tagging; initial_setup(); run_tagging()" # With parallel processing (faster): python -c "from code.file_setup.setup import initial_setup; from code.tagging.tagger import run_tagging; initial_setup(); run_tagging(parallel=True)" # With parallel processing and custom worker count: python -c "from code.file_setup.setup import initial_setup; from code.tagging.tagger import run_tagging; initial_setup(); run_tagging(parallel=True, max_workers=4)" - Rebuild only data without tagging:
# Docker: docker compose run --rm web python -c "from code.file_setup.setup import initial_setup; initial_setup()" # Local: python -c "from code.file_setup.setup import initial_setup; initial_setup()" - Run only tagging (CSVs must exist):
Note: If# Docker: docker compose run --rm web python -c "from code.tagging.tagger import run_tagging; run_tagging()" # Local: python -c "from code.tagging.tagger import run_tagging; run_tagging()" # With parallel processing (faster): python -c "from code.tagging.tagger import run_tagging; run_tagging(parallel=True)" # With parallel processing and custom worker count: python -c "from code.tagging.tagger import run_tagging; run_tagging(parallel=True, max_workers=4)"THEME_MIN_CARDS> 1 (default: 5), theme stripping automatically runs after tagging completes. This removes low-card themes from parquet files, catalog YAML, and rebuilds theme_list.json. SetTHEME_MIN_CARDS=1to disable automatic stripping. - Rebuild only the commander catalog:
# Docker: docker compose run --rm web python -m code.scripts.refresh_commander_catalog # Local: python -m code.scripts.refresh_commander_catalog
Owned Library
Keep track of cards you own.
- Upload
.txtor.csvlists; the app enriches and deduplicates entries. - Owned-only and Prefer-owned build modes live in the New Deck modal.
owned_cards/is persisted via volume mounting (OWNED_CARDS_DIR=/app/owned_cards).- Enable virtualization for large libraries with
WEB_VIRTUALIZE=1.
Browse Commanders
Explore the curated commander catalog.
- Powered by
csv_files/commander_cards.csv. - Toggle the tile with
SHOW_COMMANDERS=1. - Refresh via Initial Setup or the commander catalog script above.
- MDFC merges and compatibility snapshots are handled automatically; use
--compat-snapshoton the refresh script to emit an unmerged snapshot.
Browse Cards
Search and explore all 29,839 Magic cards.
- Search & Filters: Smart autocomplete for card names and themes, multi-theme filtering (up to 5), color identity, type, rarity, CMC range, power/toughness
- Sorting: Name A-Z/Z-A, CMC Low/High, Power High, EDHREC Popular
- Card Details (optional): Enable with
ENABLE_CARD_DETAILS=1for individual card pages with similar card recommendations - Keyboard Shortcuts:
Enterto add matches,Shift+Enterto apply filters, doubleEscto clear all - Shareable URLs: Filter state persists in URL for easy sharing
- Fast lookups powered by pre-built card index and optional similarity cache (
SIMILARITY_CACHE_ENABLED=1)
Browse Themes
Investigate theme synergies and diagnostics.
ENABLE_THEMES=1keeps the tile visible (default).- Theme cards display three badge types:
- Quality (Excellent/Good/Fair/Poor) — editorial score based on synergy depth and card count. Toggle with
SHOW_THEME_QUALITY_BADGES. - Pool size (Vast/Large/Moderate/Small/Tiny) — number of on-theme cards in the catalog. Toggle with
SHOW_THEME_POOL_BADGES. - Popularity — how often the theme appears in builds. Toggle with
SHOW_THEME_POPULARITY_BADGES. - Filter chips let you narrow the catalog by any badge combination. Toggle with
SHOW_THEME_FILTERS.
- Quality (Excellent/Good/Fair/Poor) — editorial score based on synergy depth and card count. Toggle with
- Extra tooling (
/themes/metrics, uncapped synergies, editorial quality) is gated byWEB_THEME_PICKER_DIAGNOSTICS=1. - Rebuild the merged catalog as needed:
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.build_theme_catalog" - Generate the normalized supplemental theme catalog (commander & card counts) for user-added themes:
Addpython -m code.scripts.generate_theme_catalog --output config/themes/theme_catalog.csv--logs-dir logs/generatedto mirror the CSV for diffing, or--csv-dirto point at alternate datasets. - Advanced editorial knobs (
EDITORIAL_*,SPLASH_ADAPTIVE, etc.) live in.env.exampleand are summarized in the env table below.
Finished Decks
Review, compare, and export previous builds.
- Reads from the
deck_files/volume. - Compare view can diff two builds, copy summaries, and download text lists.
- Locks, replace history, and compliance metadata persist per deck.
Random Build
Spin up surprise decks with deterministic fallbacks.
- Enable backend endpoints with
RANDOM_MODES=1and the UI tile withRANDOM_UI=1. - Fine-tune with
RANDOM_MAX_ATTEMPTS,RANDOM_TIMEOUT_MS,RANDOM_PRIMARY_THEME,RANDOM_SEED, andRANDOM_AUTO_FILL. - Random flows honor include/exclude lists, owned filters, and bracket enforcement.
Diagnostics
Peek at health & performance.
- Enabled via
SHOW_DIAGNOSTICS=1. /diagnosticssummarizes system status, feature flags, and theme metrics./diagnostics/qualityshows the theme quality dashboard: catalog health overview, badge distribution, and editorial scoring breakdown./healthzoffers a lightweight probe ({status, version, uptime_seconds}).- Press
vinside virtualized lists (whenWEB_VIRTUALIZE=1) to view grid diagnostics.
View Logs
Tail and download logs without leaving the browser.
- Enabled via
SHOW_LOGS=1. /logsshows recent entries, filtering, and copy-to-clipboard.- Raw files live under the mounted
logs/directory. /status/logs?tail=Nreturns JSON payloads for automation.
CLI & headless flows
The CLI and headless runners share the builder core.
- Launch menu-driven CLI:
python code/main.py. - Run headless (non-interactive) builds:
python code/headless_runner.py --config config/deck.json. - In Docker, set
APP_MODE=cli(and optionallyDECK_MODE=headless) to switch the container entrypoint to the CLI. - Config precedence is CLI prompts > environment variables > JSON config > defaults.
- Dual-commander support (feature-flagged):
--secondary-commanderor--background(mutually exclusive) can be supplied alongside--enable-partner-mechanics trueorENABLE_PARTNER_MECHANICS=1; Partner With and Doctor/Doctor’s Companion pairings auto-resolve (respecting opt-outs), dry runs echo the resolved pairing, and JSON configs may includesecondary_commander,background, andenable_partner_mechanicskeys.
Budget Mode
Control per-card cost to build within a price target.
- Enable with
ENABLE_BUDGET_MODE=1(default: on). Adds budget controls and a price summary panel to the builder. - Set a per-card price ceiling in the New Deck modal (UI input — not an env var).
- Soft enforcement only: cards exceeding the ceiling are filtered from the selection pool, but no cards are hard-rejected from the final result. A budget summary shows total cost and flags over-budget cards for review.
- Pool tolerance (
BUDGET_POOL_TOLERANCE, default0.15): fractional headroom above the ceiling before exclusion (e.g.0.15= 15%). Smooths results for borderline-priced cards. - Price data is sourced from Scryfall bulk data and cached locally.
PRICE_LAZY_REFRESH=1refreshes stale entries in the background. - See
docs/user_guides/budget_mode.mdfor the full guide, FAQ, and export details. (guide coming in Tier 2 docs)
Smart Land Bases
Automatic land count and basics-to-duals ratio based on deck speed and color intensity.
- Enable with
ENABLE_SMART_LANDS=1(default: on in Docker). - Speed detection: commander CMC blended with pool average CMC determines fast (33 lands), mid (35), or slow (37–39) targets.
- Profile selection: 1–2 color / low-pip decks get a basics-heavy profile; 3+ color / high-pip decks get a fixing-heavy profile with minimal basics.
- ETB tapped tolerance is adjusted automatically — fast decks avoid tapped lands; slow decks tolerate more.
- The Land Summary section shows a "Smart Lands" notice explaining the chosen profile in plain English.
- Override with
LAND_PROFILE=basics|mid|fixingorLAND_COUNT=<n>env vars. - See
docs/user_guides/land_bases.mdfor the full guide.
Data, exports, and volumes
| Host path | Container path | Purpose |
|---|---|---|
deck_files/ |
/app/deck_files |
CSV/TXT exports, compliance JSON, summary JSON |
logs/ |
/app/logs |
Application logs, taxonomy snapshots |
csv_files/ |
/app/csv_files |
Card datasets, commander catalog, tagging metadata |
config/ |
/app/config |
JSON configs, bracket policies, themes, card lists |
owned_cards/ |
/app/owned_cards |
Uploaded owned-card libraries |
Exports follow a stable naming scheme and include a .summary.json sidecar containing deck metadata, resolved themes, combined commander payloads, and lock history.
Environment variables
Most defaults are defined in docker-compose.yml and documented in .env.example. Highlights:
Core modes & networking
| Variable | Default | Purpose |
|---|---|---|
APP_MODE |
web |
Switch between Web UI (web) and CLI (cli). |
DECK_MODE |
(unset) | headless auto-runs the builder in CLI mode. |
DECK_CONFIG |
/app/config/deck.json |
Points the headless runner at a config file or folder. |
HOST / PORT / WORKERS |
0.0.0.0 / 8080 / 1 |
Uvicorn settings for the web server. |
Partner / Background mechanics (feature-flagged)
| Variable | Default | Purpose |
|---|---|---|
ENABLE_PARTNER_MECHANICS |
0 |
Unlock partner/background commander inputs for headless runs and the web builder Step 2 UI. |
ENABLE_PARTNER_SUGGESTIONS |
0 |
Surface partner/background/Doctor suggestion chips backed by config/analytics/partner_synergy.json (auto-regenerated when missing; override path with PARTNER_SUGGESTIONS_DATASET). |
Homepage visibility & UX
| Variable | Default | Purpose |
|---|---|---|
SHOW_SETUP |
1 |
Show the Initial Setup tile. |
SHOW_LOGS |
1 |
Enable the logs viewer tile and endpoints. |
SHOW_DIAGNOSTICS |
1 |
Unlock diagnostics views and overlays. |
SHOW_COMMANDERS |
1 |
Enable the commander browser. |
ENABLE_THEMES |
1 |
Keep the theme browser and selector active. |
ENABLE_CUSTOM_THEMES |
1 |
Surface the Additional Themes section in the New Deck modal. |
SHOW_THEME_QUALITY_BADGES |
1 |
Show quality badges in theme catalog (editorial quality score). |
SHOW_THEME_POOL_BADGES |
1 |
Show pool size badges in theme catalog (total available cards). |
SHOW_THEME_POPULARITY_BADGES |
1 |
Show popularity badges in theme catalog (usage frequency). |
SHOW_THEME_FILTERS |
1 |
Show filter dropdowns and quick chips in theme catalog. |
THEME_POOL_SECTIONS |
1 |
Group themes by pool size sections (Vast/Large/Moderate/Small/Tiny). Set to 0 for a flat sorted list. |
WEB_VIRTUALIZE |
1 |
Opt into virtualized lists for large datasets. |
ALLOW_MUST_HAVES |
1 |
Enforce include/exclude (must-have) lists. |
SHOW_MUST_HAVE_BUTTONS |
0 |
Reveal the must include/exclude buttons and quick-add UI (requires ALLOW_MUST_HAVES=1). |
THEME |
dark |
Default UI theme (system, light, or dark). |
Budget Mode
| Variable | Default | Purpose |
|---|---|---|
ENABLE_BUDGET_MODE |
1 |
Enable budget controls and price display throughout the builder. |
BUDGET_POOL_TOLERANCE |
0.15 |
Fractional overhead above the per-card ceiling before a card is excluded from the selection pool (e.g. 0.15 = 15%). |
PRICE_AUTO_REFRESH |
0 |
Rebuild price cache automatically once daily at 01:00 UTC. |
PRICE_LAZY_REFRESH |
1 |
Refresh stale per-card prices in the background (7-day TTL). |
PRICE_STALE_WARNING_HOURS |
24 |
Hours before a cached price is marked stale with a visual indicator. Set to 0 to disable. |
Smart Land Bases
| Variable | Default | Purpose |
|---|---|---|
ENABLE_SMART_LANDS |
1 |
Enable automatic land count and profile selection based on commander speed and pip density. |
LAND_PROFILE |
(auto) | Force a specific profile: basics, mid, or fixing. Skips auto-detection. |
LAND_COUNT |
(auto) | Force total land count (e.g. 36). Skips curve calculation. |
Random build tuning
| Variable | Default | Purpose |
|---|---|---|
RANDOM_MODES |
(unset) | Expose random build endpoints. |
RANDOM_UI |
(unset) | Show the Random Build homepage tile. |
RANDOM_MAX_ATTEMPTS |
5 |
Retry budget when constraints are tight. |
RANDOM_TIMEOUT_MS |
5000 |
Per-attempt timeout in milliseconds. |
RANDOM_REROLL_THROTTLE_MS |
350 |
Minimum milliseconds between reroll requests (client-side guard). |
RANDOM_STRUCTURED_LOGS |
0 |
Emit structured JSON logs for random builds. |
RANDOM_TELEMETRY |
0 |
Enable lightweight timing/attempt metrics for diagnostics. |
RANDOM_PRIMARY_THEME / RANDOM_SECONDARY_THEME / RANDOM_TERTIARY_THEME |
(blank) | Override selected themes. |
RANDOM_SEED |
(blank) | Deterministic seed for reproducible builds. |
RANDOM_AUTO_FILL |
1 |
Allow auto-fill of missing theme slots. |
Random rate limiting (optional)
| Variable | Default | Purpose |
|---|---|---|
RATE_LIMIT_ENABLED |
0 |
Enable server-side rate limiting for random endpoints. |
RATE_LIMIT_WINDOW_S |
10 |
Rolling window size in seconds. |
RATE_LIMIT_RANDOM |
10 |
Max random attempts per window. |
RATE_LIMIT_BUILD |
10 |
Max full builds per window. |
RATE_LIMIT_SUGGEST |
30 |
Max suggestion calls per window. |
Automation & performance
| Variable | Default | Purpose |
|---|---|---|
WEB_AUTO_SETUP |
1 |
Auto-run setup when artifacts are missing or stale. |
WEB_AUTO_REFRESH_DAYS |
7 |
Refresh cards.csv if older than N days. |
WEB_TAG_PARALLEL |
1 |
Enable parallel tagging workers. |
WEB_TAG_WORKERS |
4 |
Worker count for tagging (compose default). |
CACHE_CARD_IMAGES |
0 |
Download card images to card_files/images/ (1=enable, 0=fetch from API on demand). Requires ~3-6 GB. |
WEB_AUTO_ENFORCE |
0 |
Auto-apply bracket enforcement after builds. |
WEB_THEME_PICKER_DIAGNOSTICS |
1 |
Enable theme diagnostics endpoints. |
THEME_MIN_CARDS |
5 |
Minimum card count for themes. Themes with fewer cards are stripped from catalogs, JSON files, and parquet metadata during setup/tagging. Set to 1 to keep all themes. |
Paths & overrides
| Variable | Default | Purpose |
|---|---|---|
CSV_FILES_DIR |
/app/csv_files |
Alternate dataset location (useful for tests). |
DECK_EXPORTS |
/app/deck_files |
Override where exports land. |
OWNED_CARDS_DIR / CARD_LIBRARY_DIR |
/app/owned_cards |
Override owned library path. |
CARD_INDEX_EXTRA_CSV |
(blank) | Inject extra CSV data into the card index. |
Testing aids
| Variable | Default | Purpose |
|---|---|---|
EDITORIAL_TEST_USE_FIXTURES |
0 |
When set to 1, editorial governance tests stage lightweight catalog fixtures instead of requiring generated YAML/JSON data. |
Supplemental themes
| Variable | Default | Purpose |
|---|---|---|
DECK_ADDITIONAL_THEMES |
(blank) | Comma/semicolon separated list of supplemental themes to apply in headless builds. |
THEME_MATCH_MODE |
permissive |
Controls fuzzy resolution strictness (strict blocks unresolved themes) and seeds the web UI default. |
USER_THEME_LIMIT |
8 |
Maximum number of user-supplied themes allowed in the web builder. |
Refer to .env.example for advanced editorial, taxonomy, and experimentation knobs (EDITORIAL_*, SPLASH_ADAPTIVE, WEB_THEME_FILTER_PREWARM, etc.). Document any newly introduced variables in the README, DOCKER guide, compose files, and .env.example.
Project layout
code/ FastAPI app, deckbuilding engine, CLI, scripts, and tests
├─ web/ Web UI (FastAPI + Jinja2 + HTMX)
├─ deck_builder/ Core builder logic and services
├─ tagging/ Tag pipelines and utilities
├─ locks/ Card locking utilities
├─ scripts/ Maintenance and editorial tools
├─ tests/ Pytest suite (web, CLI, random, tagging)
config/ JSON configs, bracket policies, themes, card lists
csv_files/ Card datasets, commander catalog, theme outputs
owned_cards/ User-supplied owned lists
logs/ Application logs and taxonomy snapshots
deck_files/ Generated deck exports (CSV/TXT/JSON)
Development setup
- Create and activate the virtual environment:
python -m venv .venv .\venv\Scripts\Activate.ps1 - Install dependencies:
pip install -r requirements.txt -r requirements-dev.txt - Run the web app locally:
uvicorn code.web.app:app --host 127.0.0.1 --port 8080 - Run tests (prefer targeted files—no wildcards):
UseC:/Users/Matt/mtg_python/mtg_python_deckbuilder/.venv/Scripts/python.exe -m pytest -q code/tests/test_random_determinism.py code/tests/test_permalinks_and_locks.pytasks.jsonentries such aspytest-fast-randomorpytest-fast-locksfor quick feedback. - Linting and type checks follow
pyproject.toml/mypy.inidefaults. Keep changes minimal and well-typed.
When adding features, favor the web UI first, keep public builder APIs stable, and update documentation (CHANGELOG → RELEASE_NOTES_TEMPLATE → DOCKER → README) in that order.
Troubleshooting
- Blank page after start: Visit
/healthz, check/logs, ensureSHOW_LOGS=1, and inspect hostlogs/for stack traces. - Stale data: Run Initial Setup or delete
csv_files/.tagging_complete.jsonto force reseeding. - Owned-only build fails: Confirm owned files were uploaded correctly and that
owned_cards/is mounted. - Random build stalls: Lower
RANDOM_MAX_ATTEMPTS, increaseRANDOM_TIMEOUT_MS, and verify selected themes exist via/themes/. - Commander list outdated: Rerun the commander refresh script or Initial Setup.
Contributing
Pull requests are welcome—follow the conventional commit style, keep diffs focused, add or update tests when behavior changes, and document new env vars or workflows. Review CONTRIBUTING_EDITORIAL.md for editorial tooling guidance.
License & attribution
Licensed under the MIT License. Card data and imagery are provided by Scryfall; please respect their API terms.
Further reading
- Random mode developer guide – architecture, seed infrastructure, and diagnostic tooling for the random build system.
- Random mode diagnostics – runtime metrics, telemetry flags, and structured log formats.
- Web backend: error handling – structured error responses, request IDs, and logging conventions.
- Web backend: route patterns – HTMX conventions, partial templates, and routing standards.
- Node dependencies – why Node/npm is present (Tailwind CSS build only; no runtime JS framework).