A beautiful, intelligent Commander deck builder powered by Scryfall, bracket scoring, and AI suggestions.
- 🔍 Scryfall search — full syntax support, commander mode, By Set, By Color
- 🎨 Card printing selector — choose your preferred art before adding or swap it anytime from the deck list
- 🃏 Drag & drop deck builder — list and grid views, categorized zones; commander pinned first in grid view
- 📊 Live bracket scoring — 6-dimension analysis (ramp, draw, removal, tutors, win speed, CMC)
- 📐 Format-specific stats — curve, threat density and interaction ratio benchmarked per format for non-Commander decks
- ⚡ Game Changers detection — auto-warns when you cross bracket thresholds
- 🧭 Mana alignment & turn-1 odds — pips asked vs sources produced, per-colour land targets, exact hypergeometric odds that the opening seven holds a land and a one-drop
- 🤖 AI suggestions & deck builder — Anthropic Claude or OpenAI GPT analyzes your deck and recommends cards + cuts; the builder drafts a full list from 10 archetype templates with budget constraints and per-card reasoning
- 🤝 Partner pairing — Partner, Partner With, Friends Forever, Background, Doctor's Companion, Character Select (TMNT) — filtered search per pairing type
- 📦 Companion (Ikoria) — dedicated slot + Companion search mode, rule hints, color/mechanical warnings (not the same as Sideboard pile cards)
- 📤 Multi-format export — Moxfield, MTG Arena, MTGO (.dek), TappedOut, Archidekt (with category tags), Manabox, MTGGoldfish, EDHRec deck-check, Plain Text
- 📥 Import from URL or text — paste a Moxfield, Archidekt, TappedOut, MTGTop8 or MTGDecks.net link (auto-detected, rate-limited, honours
robots.txt) or a Moxfield-style text list - 🖨️ Proxy sheets — print-ready 63×88 mm pages (3×3 A4/Letter or 2×2), with card art or text-only boxes; printed in the viewer's language
- 📈 Commander meta panel — EDHRec's top cards for your commander with one-click add, plus recent MTGTop8 tournament decks with player, event, placement and date
- 👑 Set as commander — crown icon on any deck card promotes it to commander slot
- 🔢 Card quantities — +/- buttons for basic lands and Commander-legal multiples (auto-detected via oracle text)
- 📝 Deck notes & tags — per-card notes, deck description, colored tag pills
- 📸 Deck snapshots — save and restore deck states at any point
- 🔗 Deck sharing — generate a shareable read-only link
- 🌍 Community discovery — public deck listing per commander at
/commanders/<slug>/decks, ranked by up/down votes, with star ratings, reviews, threaded comments and user follows - 🎮 Playtest mode — opening hand and London mulligan, turn phases (Untap → End), life tracking with history and undo, and battlefield / graveyard / exile zones with tap and counters; starting life follows the deck format
- 📒 Playtest analytics — record how each goldfish run went (result, turns, mulligans, opponent strength) and read win rate, mulligan distribution and matchup splits per deck
- ⌨️ Keyboard shortcuts — power-user navigation with undo stack
- 🎴 Multi-format support — Commander, Brawl, Oathbreaker, Standard, Pioneer, Modern, Legacy, Vintage, Pauper with correct rules per format
- 📦 Collection tracking — mark owned cards, shopping list with missing cost, CSV export, bulk "Mark all owned"
- ✨ 3D Spellbook landing — immersive Three.js scene for unauthenticated visitors (mobile/a11y fallback)
- 🌍 English & French — full UI in both, with a header language switcher; card names, rules text and images follow the viewer's language where a Scryfall printing exists (deck rows, tooltips, playtest, proxies, Game Changers page)
- 🌙 Dark / Light theme — persisted across sessions
- 🔒 Security hardened — Zod validation, input sanitization, no client-side secrets, CSP / HSTS / COOP headers, rate-limited auth and AI routes
| Layer | Tech |
|---|---|
| Framework | Next.js 15 (App Router) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4 |
| Components | shadcn/ui + Radix |
| Animations | Framer Motion |
| State | Zustand 5 |
| Data fetching | TanStack Query 5 |
| Database | PostgreSQL 16 + Prisma (Docker locally, Neon in production) |
| Auth | NextAuth.js v5 (Google OAuth + credentials) |
| i18n | next-intl 4 (en, fr) |
| Drag & Drop | dnd-kit 6 |
| 3D Engine | Three.js + R3F + drei |
| Animations | gsap (camera), Framer |
| Observability | Sentry, Vercel Speed Insights |
- Node.js 22+
- pnpm 10+
- Docker (for PostgreSQL)
# Clone
git clone https://github.com/KaelSensei/MagicAIBuilder.git
cd MagicAIBuilder
# Install dependencies (generates Prisma client automatically)
pnpm install
# Configure environment
cp .env.example .env.local
# Edit .env.local — DATABASE_URL is pre-filled for local Docker
# Start the database
pnpm db:up
# Run migrations
pnpm db:migrate
# Start dev server on http://localhost:3000
pnpm dev:localEnglish is served without a prefix at http://localhost:3000; French carries one, at http://localhost:3000/fr. Use the language switcher in the header to move between them.
For a quick landing-page preview without Docker, you can run pnpm dev:local
directly. Authenticated deck, collection, and profile features require
PostgreSQL via pnpm db:up and pnpm db:migrate.
pnpm db:seedCreates an Atraxa Superfriends demo deck with 100 cards, a snapshot, and collection entries.
Add one of these to .env.local for personalized AI deck analysis:
ANTHROPIC_API_KEY=sk-ant-...
# or
OPENAI_API_KEY=sk-...Without a key, the AI panel uses curated generic suggestions.
| Command | Description |
|---|---|
pnpm dev |
Start Next.js dev server |
pnpm dev:local |
Start dev server on port 3000 (IPv4 + IPv6) |
pnpm build |
Production build |
pnpm analyze |
Production build + interactive bundle map |
pnpm lint |
ESLint check |
pnpm test |
Unit tests (Vitest) |
pnpm test:e2e |
E2E tests (Playwright) |
pnpm db:up |
Start PostgreSQL via Docker |
pnpm db:down |
Stop PostgreSQL |
pnpm db:migrate |
Apply pending migrations |
pnpm db:studio |
Open Prisma Studio |
pnpm db:reset |
Reset database |
pnpm db:seed |
Seed demo data (Atraxa deck) |
The suite runs against a disposable PostgreSQL and a Chromium image, so it never touches your dev database:
docker compose -f docker-compose.e2e.yml up --build --exit-code-from e2eAlways pass --build: without it Compose reuses the previous image, and the
container runs the test files as they were when it was last built.
Dockerfile.playwright pins both the Playwright image and pnpm. The image tag
must track @playwright/test in package.json — Playwright resolves browser
binaries by a version-stamped path, so any drift makes every browser test fail
to launch. src/lib/toolchain.test.ts fails the unit suite if the pins diverge.
Two groups of tests are excluded from the blocking run by default:
| Tag | Why |
|---|---|
@external |
Calls a third-party service (e.g. the live Moxfield API). A deck going private there turns the gate red with no code change on our side. |
@perf |
Asserts wall-clock latency against next dev, which compiles routes on demand — the same endpoint measured 41 ms alone and 5163 ms under full-suite contention. |
Run them deliberately:
PLAYWRIGHT_GREP_INVERT="" docker compose -f docker-compose.e2e.yml up --build --exit-code-from e2eNarrow to one spec with PLAYWRIGHT_SPEC=e2e/playtest.spec.ts.
.husky/pre-push runs the whole suite through scripts/e2e-pre-push.sh and
blocks the push on failure. The verdict always comes from the container's exit
code. Set SKIP_E2E=1 to bypass it in an emergency.
Browser (Zustand — optimistic updates)
↕ fetch
Next.js API Routes (/api/decks/*, /api/ai/*, /api/import/url, /api/meta/*, …)
↕ Prisma Client
PostgreSQL 16 — Docker locally, Neon (Vercel Marketplace) in production
External APIs:
- Scryfall — card search, printings, localized text and images, Game Changers list, banlist (direct from browser, CORS allowed; card images go through
/api/proxy-card-imageonly for print) - Commander Spellbook — combo detection (proxied via /api/combos)
- EDHRec — top cards per commander (server-side, cached 24h in
MetaCache) - MTGTop8 / MTGDecks / Moxfield / Archidekt / TappedOut — deck import by URL and tournament meta (server-side, rate-limited,
robots.txtrespected) - Anthropic / OpenAI — AI suggestions and deck builder (server-side only, key never exposed to client)
See docs/security/security.md for the threat model and architecture, and docs/security/production-checklist.md for the 20-point production checklist with a status per item (audited 2026-08-20).
Key points:
- All API keys are server-side only; the client sees
NEXT_PUBLIC_*values and nothing else - Input validation via Zod on API routes; HTML sanitization on user-controlled strings
- Content-Security-Policy, HSTS, COOP/CORP and the classic hardening headers, built and unit-tested in
src/lib/security-headers.ts - Ownership checks (
requireAuth/requireDeckOwner) on every mutating route; generic error messages, details stay in the logs - Login, signup, AI and import routes are rate-limited; JWT sessions expire after 7 days
- Commander Spellbook and card images proxied to avoid CORS and SSRF vectors (host allowlist,
image/*only, 5 MB cap)
Maintained by Marco — The Bug Whisperer. See
docs/engineering/quality-gate.mdfor full details and history.
| Metric | Baseline | Minimum |
|---|---|---|
| Coverage | 94.3% | ≥ 90% |
| Bugs | 0 | = 0 |
| Vulnerabilities | 0 | = 0 |
| Code Smells | 1 | ≤ 5 |
| Duplicated Lines | 1.8% | ≤ 3.0% |
| Reliability | A | A |
| Security | A | A |
A PR that degrades any of these metrics is blocked until fixed.
docs/ is organized by audience and purpose (product, engineering, project tracking, security).
docs/
engineering/
dx-ci-overview.md # CI/DX overview: pipelines, local dev checks, quality tooling
infrastructure.md # Infra + hosting notes (Vercel, DB, storage, observability)
quality-gate.md # Quality thresholds + Sonar/CI expectations
technical.md # Technical architecture: modules, data flow, DB, patterns
product/
companion-implementation.md # Ikoria Companion product/rules (linked from user stories)
competitive-landscape.md # Competitor analysis / positioning notes
project-spec.md # Product/engineering spec: scope, UX, rules, implementation notes
roadmap.md # Future work backlog: technical + functional roadmap + prioritization
user-flows.md # End-to-end user journeys and flows
user-guide.md # End-user manual: how to use the app
us-detail.md # Full user stories backlog
project/
changelog.md # Release notes / history of changes
progress.md # Project checklist / milestones / tracking
security/
security.md # Threat model + security architecture + hardening rules
production-checklist.md # 20-point production checklist, status per item + follow-ups
audit-securite-2026-07-20.md # Full security audit (French)
prompt-system/ # Prompting system docs (AI behavior, prompts, conventions)
references/ # Reference material: typescript-patterns.md, banlists, game-changers, edh-themes, official-sources
rules/ # Internal rules / conventions docs (e.g. magic-comp-rules-*.txt)
init-prompt.md # Seed prompt / bootstrap notes for agent-assisted work
All shared agent resources are centralized in .agents/ as the single source of truth. Agent-specific directories (.claude/, .codex/, .cursor/) contain only symlinks and local config — they are gitignored.
.agents/ ← committed, shared across all agents
skills/ ← skill definitions
mtg-commander-analysis/ ← Commander deck analysis
mtg-learn/ ← MTG learning guide
mtg-rules/ ← Comprehensive rules engine
typescript-craftsmanship/ ← TS + React + Next.js quality rules
cursor-rules/ ← Cursor-specific .mdc rules
commands/ ← shared commands (22 workflows)
rules/ ← shared coding rules (.mdc)
docs/ ← shared documentation
hooks.json ← pre-PR quality gate hook (reference)
.claude/ ← gitignored except settings.json
settings.json ← pre-PR SonarCloud hook (committed)
skills → ../.agents/skills ← symlink
settings.local.json ← personal credentials (gitignored)
mcp.json ← MCP tokens (gitignored)
.codex/ ← entirely gitignored
skills → ../.agents/skills ← symlink
commands → ../.agents/commands
rules → ../.agents/rules
docs → ../.agents/docs
.cursor/ ← entirely gitignored
skills → ../.agents/skills ← symlink
commands → ../.agents/commands
rules → ../.agents/rules
docs → ../.agents/docs
After pnpm install, recreate the agent symlinks. A setup script is provided, or run manually:
Linux / macOS / WSL:
# Skills
cd .claude && ln -sf ../.agents/skills skills && cd ..
cd .codex && ln -sf ../.agents/skills skills && cd ..
cd .cursor && ln -sf ../.agents/skills skills && cd ..
# Commands, rules, docs (Codex & Cursor only)
cd .codex && ln -sf ../.agents/commands commands && ln -sf ../.agents/rules rules && ln -sf ../.agents/docs docs && cd ..
cd .cursor && ln -sf ../.agents/commands commands && ln -sf ../.agents/rules rules && ln -sf ../.agents/docs docs && cd ..Windows (CMD, run as Administrator):
mklink /D .claude\skills .agents\skills
mklink /D .codex\skills .agents\skills
mklink /D .cursor\skills .agents\skills
mklink /D .codex\commands .agents\commands
mklink /D .codex\rules .agents\rules
mklink /D .codex\docs .agents\docs
mklink /D .cursor\commands .agents\commands
mklink /D .cursor\rules .agents\rules
mklink /D .cursor\docs .agents\docsWindows (PowerShell, run as Administrator):
'claude','codex','cursor' | ForEach-Object {
New-Item -ItemType SymbolicLink -Path ".$_\skills" -Target ".agents\skills" -Force
}
'codex','cursor' | ForEach-Object {
'commands','rules','docs' | ForEach-Object -Begin { $agent = $_ } -Process {
New-Item -ItemType SymbolicLink -Path ".$agent\$_" -Target ".agents\$_" -Force
}
}Windows (Git Bash):
# Requires: Windows Developer Mode enabled (Settings > For developers), OR run as Administrator
for dir in .claude .codex .cursor; do
cd "$dir" && ln -sf ../.agents/skills skills && cd ..
done
for dir in .codex .cursor; do
cd "$dir" && ln -sf ../.agents/commands commands && ln -sf ../.agents/rules rules && ln -sf ../.agents/docs docs && cd ..
doneNote Windows: symlinks require either Developer Mode (Settings > For developers > Developer Mode ON) or running the terminal as Administrator. Without this,
mklink /Dandln -swill fail with "Permission denied".
Coding standards are defined in CLAUDE.md (root) and automatically loaded by Claude Code every session.
MagicAIBuilder was conceived, designed, and developed by Kael, with three AI assistants playing different roles in the story:
- Claude (Anthropic – Sonnet 4.6 / Opus 4.6) — helped bootstrap the project (Next.js + Prisma boilerplate), define the TypeScript/React architecture, and ship the very first features like deck creation and editing.
- OpenAI Codex / ChatGPT (GPT‑5.4) — brought in later for heavier work: complex features, deep refactors, proxy/export flows, database migrations, and DevOps plumbing.
- Cursor “automatic” model (GPT‑5.1) — the everyday in‑editor helper, used for fast bug‑fix passes, small refactors, and making the codebase feel “alive” while Kael iterates.
To show multiple authors on a commit, add a blank line at the end of the message body, then one or more Co-authored-by: trailers (GitHub links avatars only when the email matches an account):
| Assistant | Example trailer |
|---|---|
| Claude (Anthropic) | Co-authored-by: Claude <noreply@anthropic.com> |
| OpenAI Codex / ChatGPT | Co-authored-by: OpenAI Codex <email@example.com> — use an address tied to your GitHub user if you want it linked. |
| Cursor (Auto / Agent) | Co-authored-by: Cursor Agent <noreply@cursor.com> |
MIT
Wizards of the Coast, Magic: The Gathering, and their logos are trademarks of Wizards of the Coast LLC. © 1993-2026 Wizards. All Rights Reserved.
MagicAIBuilder is not affiliated with, endorsed, sponsored, or specifically approved by Wizards of the Coast LLC. This project operates under Wizards' Fan Site Policy. MAGIC: THE GATHERING® is a trademark of Wizards of the Coast.
Some card prices and other card data are provided by Scryfall. Scryfall makes no guarantee about its price information.
See LEGAL.md for full legal notices.
