# alebl/magic-the-gathering-deckforge architecture

> Architecture diagram of the GitHub repository alebl/magic-the-gathering-deckforge, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-07). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/alebl/magic-the-gathering-deckforge
- Repository: https://github.com/alebl/magic-the-gathering-deckforge

## Overview

#### Purpose and Runtime

MTG Deck Forge is a local-first Magic: The Gathering card search, deck-building, analysis, proxy-printing, and playtest application. The primary runtime is a React 19/TypeScript renderer built by Vite; it runs either in a browser or inside Electron. Electron’s privileged boundary is defined by `electron/index.ts` and `electron/preload.ts`.

#### Application Composition and Entry Points

The renderer starts at `src/main.tsx`, mounts the application in `src/App.tsx`, and is framed by shared navigation/layout in `src/components/layout/RootLayout.tsx`. Domain UI is organized around card collection, deck editing, statistics, and playtesting rather than route-specific server endpoints. Shared types provide the central domain model: `src/types/Card.ts`, `src/types/Deck.ts`, and `src/types/Playtest.ts`.

#### Card Discovery and Collection

Card discovery is driven by debounced Scryfall-backed search and filter state through `src/hooks/useCardSearch.ts` and `src/hooks/useSearchFilters.ts`; results render through `src/components/card/CardGrid.tsx` and card details/actions through `src/components/card/CardDetailModal.tsx`. Collection ownership and filtering form a separate local concern in `src/hooks/useCollection.ts`, `src/hooks/useCollectionOwnership.ts`, and `src/components/collection/CollectionManager.tsx`. This boundary keeps remote card metadata distinct from user-owned inventory.

#### Deck Lifecycle and Persistence

Deck editing is centered on `src/components/deck/DeckEditWorkspace.tsx`, with global selected-deck and deck-list state in `src/store/useDeckStore.ts`. High-level lifecycle actions—create/edit/save/load/delete—are coordinated in `src/hooks/useDeckManager.ts` and `src/hooks/useDeckActions.ts`. Persistent local storage is configured in `src/db/database.ts`, while deck interchange/version capabilities live in `src/services/deckImportService.ts`, `src/services/deckShare.ts`, and `src/services/deckVersionService.ts`. Decks can therefore flow between UI state, IndexedDB, and import/export files without requiring an application backend.

#### Validation, Suggestions, and Analytics

Pure domain calculations sit behind the editing UI: legality and deck rules in `src/utils/deckValidator.ts`, deck metrics in `src/utils/deckStatistics.ts`, and automated recommendations in `src/utils/deckSuggestions.ts`. Their visual consumers are `src/components/deck/DeckValidationBadge.tsx`, `src/components/stats/DeckStats.tsx`, and `src/components/deck/DeckSuggestionsModal.tsx`. Scryfall is also an external legality/data authority, while local calculations provide immediate deck feedback.

#### Tokens, Printing, and Playtesting

Token requirements are derived from deck card data through `src/hooks/useDeckTokens.ts` and managed in `src/components/deck/DeckTokensTab.tsx`. Proxy-print configuration and output are handled by `src/hooks/useProxyPrint.ts` and `src/components/deck/DeckProxyPrint.tsx`. The playtest simulator has isolated interaction state in `src/components/playtest/PlaytestContext.tsx`, behavior in `src/hooks/usePlaytestSimulator.ts`, and its primary workspace in `src/components/playtest/PlaytestSimulator.tsx`; it consumes an assembled deck but models transient gameplay separately from persisted deck data.

#### Cross-Cutting Boundaries

Localization is initialized in `src/plugins/i18n.ts` with language catalogs in `src/locales/en.ts`, `src/locales/es.ts`, and `src/locales/pt.ts`. Application-level preferences include collection settings in `src/store/useCollectionSettings.ts` and browser persistence keys in `src/constants/storage.ts`. Network availability is surfaced through `src/hooks/useOnlineStatus.ts`, important because card search and legality checks depend on the external Scryfall API, while decks and collections remain available from local IndexedDB.

Main entry points: [`src/store/useDeckStore.ts`](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/store/useDeckStore.ts) (Deck store), [`src/components/layout/RootLayout.tsx`](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/layout/RootLayout.tsx) (Root layout), [`src/App.tsx`](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/App.tsx) (Application shell), [`src/components/deck/DeckEditWorkspace.tsx`](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/deck/DeckEditWorkspace.tsx) (Deck editor)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_renderer["React renderer"]
  node_main["Renderer entry<br/>React entry<br/>[main.tsx]"]
  node_app["Application shell<br/>React app<br/>[App.tsx]"]
  node_layout["Root layout<br/>navigation layout<br/>[RootLayout.tsx]"]
  node_card_search["Card search<br/>search hook<br/>[useCardSearch.ts]"]
  node_card_ui["Card browser<br/>card UI<br/>[CardGrid.tsx]"]
  node_collection["Collection manager<br/>collection UI"]
  node_deck_workspace["Deck editor<br/>editing workspace"]
end

subgraph group_deck["Deck domain"]
  node_deck_store["Deck store<br/>global state<br/>[useDeckStore.ts]"]
  node_deck_manager["Deck lifecycle<br/>manager hooks<br/>[useDeckManager.ts]"]
  node_indexeddb[("Local database<br/>IndexedDB<br/>[database.ts]")]
  node_deck_interchange["Deck interchange<br/>import/share/version services"]
end

subgraph group_tools["Deck tools"]
  node_validation["Deck validation<br/>rules engine<br/>[deckValidator.ts]"]
  node_analytics["Deck analytics<br/>calculation engines<br/>[deckStatistics.ts]"]
  node_deck_feedback["Deck feedback UI<br/>validation/stats UI<br/>[DeckStats.tsx]"]
  node_tokens["Token planner<br/>token workflow<br/>[useDeckTokens.ts]"]
  node_proxy_print["Proxy printing<br/>print workflow<br/>[useProxyPrint.ts]"]
  node_playtest["Playtest simulator<br/>transient simulation"]
end

subgraph group_platform["Platform services"]
  node_scryfall{{"Scryfall API<br/>external card authority"}}
  node_electron["Electron boundary<br/>main/preload<br/>[index.ts]"]
  node_i18n["Localization<br/>i18n plugin<br/>[i18n.ts]"]
end

node_main -->|"mounts"| node_app
node_app -->|"frames"| node_layout
node_layout -->|"hosts"| node_card_ui
node_layout -->|"hosts"| node_collection
node_layout -->|"hosts"| node_deck_workspace
node_card_ui -->|"uses"| node_card_search
node_card_search -->|"searches"| node_scryfall
node_collection -->|"persists ownership"| node_indexeddb
node_deck_workspace -->|"edits"| node_deck_store
node_deck_workspace -->|"invokes lifecycle"| node_deck_manager
node_deck_manager -->|"updates"| node_deck_store
node_deck_manager -->|"saves and loads"| node_indexeddb
node_deck_interchange -->|"imports and exports"| node_indexeddb
node_deck_store -->|"deck data"| node_validation
node_deck_store -->|"deck data"| node_analytics
node_validation -->|"legality"| node_deck_feedback
node_analytics -->|"metrics and suggestions"| node_deck_feedback
node_deck_store -->|"deck cards"| node_tokens
node_deck_store -->|"deck contents"| node_proxy_print
node_deck_store -->|"assembled deck"| node_playtest
node_app -->|"initializes"| node_i18n
node_electron -.->|"hosts renderer"| node_main

click node_main "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/main.tsx"
click node_app "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/App.tsx"
click node_layout "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/layout/RootLayout.tsx"
click node_card_search "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useCardSearch.ts"
click node_card_ui "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/card/CardGrid.tsx"
click node_collection "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/collection/CollectionManager.tsx"
click node_deck_workspace "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/deck/DeckEditWorkspace.tsx"
click node_deck_store "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/store/useDeckStore.ts"
click node_deck_manager "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useDeckManager.ts"
click node_indexeddb "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/db/database.ts"
click node_deck_interchange "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/services/deckImportService.ts"
click node_validation "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/utils/deckValidator.ts"
click node_analytics "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/utils/deckStatistics.ts"
click node_deck_feedback "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/stats/DeckStats.tsx"
click node_tokens "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useDeckTokens.ts"
click node_proxy_print "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useProxyPrint.ts"
click node_playtest "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/playtest/PlaytestSimulator.tsx"
click node_electron "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/electron/index.ts"
click node_i18n "https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/plugins/i18n.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_app,node_layout,node_card_search,node_card_ui,node_collection,node_deck_workspace toneBlue
class node_deck_store,node_deck_manager,node_indexeddb,node_deck_interchange toneAmber
class node_validation,node_analytics,node_deck_feedback,node_tokens,node_proxy_print,node_playtest toneMint
class node_scryfall,node_electron,node_i18n toneRose
```

## Components

### React renderer

Local-first user interface and domain workflows.

- [Renderer entry](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/main.tsx): React entry · `src/main.tsx`
- [Application shell](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/App.tsx): React app · `src/App.tsx`
- [Root layout](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/layout/RootLayout.tsx): navigation layout · `src/components/layout/RootLayout.tsx`
- [Card search](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useCardSearch.ts): search hook · Debounced Scryfall search and filter state. · `src/hooks/useCardSearch.ts`
- [Card browser](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/card/CardGrid.tsx): card UI · Search results and card actions. · `src/components/card/CardGrid.tsx`
- [Collection manager](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/collection/CollectionManager.tsx): collection UI · Separates owned inventory from card metadata. · `src/components/collection/CollectionManager.tsx`
- [Deck editor](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/deck/DeckEditWorkspace.tsx): editing workspace · `src/components/deck/DeckEditWorkspace.tsx`

### Deck domain

Deck state, lifecycle, and local persistence.

- [Deck store](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/store/useDeckStore.ts): global state · Selected deck and deck-list state. · `src/store/useDeckStore.ts`
- [Deck lifecycle](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useDeckManager.ts): manager hooks · Coordinates create, edit, save, load, and delete actions. · `src/hooks/useDeckManager.ts`
- [Local database](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/db/database.ts): IndexedDB · Persistent local deck storage. · `src/db/database.ts`
- [Deck interchange](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/services/deckImportService.ts): import/share/version services · Import/export, sharing, and version capabilities. · `src/services/deckImportService.ts`

### Deck tools

Derived deck capabilities and isolated simulators.

- [Deck validation](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/utils/deckValidator.ts): rules engine · Pure legality and deck-rule calculations. · `src/utils/deckValidator.ts`
- [Deck analytics](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/utils/deckStatistics.ts): calculation engines · Statistics and automated recommendations. · `src/utils/deckStatistics.ts`
- [Deck feedback UI](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/stats/DeckStats.tsx): validation/stats UI · Visualizes validation, metrics, and suggestions. · `src/components/stats/DeckStats.tsx`
- [Token planner](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useDeckTokens.ts): token workflow · Derives and manages token requirements. · `src/hooks/useDeckTokens.ts`
- [Proxy printing](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/hooks/useProxyPrint.ts): print workflow · Configures and produces proxy output. · `src/hooks/useProxyPrint.ts`
- [Playtest simulator](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/components/playtest/PlaytestSimulator.tsx): transient simulation · Isolated gameplay state for an assembled deck. · `src/components/playtest/PlaytestSimulator.tsx`

### Platform services

Desktop boundary, localization, and external data.

- **Scryfall API**: external card authority · Remote card metadata and legality authority.
- [Electron boundary](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/electron/index.ts): main/preload · Privileged desktop integration boundary. · `electron/index.ts`
- [Localization](https://github.com/alebl/magic-the-gathering-deckforge/blob/main/src/plugins/i18n.ts): i18n plugin · Initializes language catalogs. · `src/plugins/i18n.ts`

## Connections

- Renderer entry → Application shell: mounts
- Application shell → Root layout: frames
- Root layout → Card browser: hosts
- Root layout → Collection manager: hosts
- Root layout → Deck editor: hosts
- Card browser → Card search: uses
- Card search → Scryfall API: searches
- Collection manager → Local database: persists ownership
- Deck editor → Deck store: edits
- Deck editor → Deck lifecycle: invokes lifecycle
- Deck lifecycle → Deck store: updates
- Deck lifecycle → Local database: saves and loads
- Deck interchange → Local database: imports and exports
- Deck store → Deck validation: deck data
- Deck store → Deck analytics: deck data
- Deck validation → Deck feedback UI: legality
- Deck analytics → Deck feedback UI: metrics and suggestions
- Deck store → Token planner: deck cards
- Deck store → Proxy printing: deck contents
- Deck store → Playtest simulator: assembled deck
- Application shell → Localization: initializes
- Electron boundary → Renderer entry: hosts renderer
