Repository navigation
Integración con Scryfall
English · Español
Todo el contacto con Scryfall ocurre en Rust, en src-tauri/src/scryfall/. El módulo ofrece un único cliente HTTP con límite de ritmo y reintentos, una caché de búsquedas en memoria, una caché persistente de cartas en SQLite y el flujo que convierte una lista parseada en cartas con sus imágenes guardadas en el almacén de blobs. La vista web nunca habla con la red.
Límites: la sintaxis de la lista es Parseo de la lista del mazo; las fuentes que no son Scryfall (fichas de Cockatrice, nombres en otros idiomas) son Fuentes externas; vincular una imagen propia del usuario con una carta real es Identificación de cartas y OCR.
| Fichero | Responsabilidad |
|---|---|
src-tauri/src/scryfall/client.rs |
Scryfall (la única puerta a api.scryfall.com), trait CardApi, Simbolo. |
src-tauri/src/scryfall/rate.rs |
Limitador: separación mínima entre peticiones a la API. |
src-tauri/src/scryfall/busquedas.rs |
Busquedas: caché en memoria de una hora para los resultados de búsqueda, acotada por la RAM. |
src-tauri/src/scryfall/cache.rs |
guardar, leer, leer_impresion: caché persistente de cartas (tabla scryfall_cards). |
src-tauri/src/scryfall/models.rs |
ScryCard, CardFace, ImageUris, Identifier, Collection, SearchPage, SetInfo... |
src-tauri/src/scryfall/resolve.rs |
resolve(): el flujo lista -> cartas; trait Guardar; ResolveOptions, ImagePolicy. |
src-tauri/src/scryfall/fichas_auto.rs |
Detección de fichas mediante all_parts (fichas_de, faltan_en_el_deck). |
src-tauri/src/scryfall/fichas.rs |
Tabla de tipo de ficha en español -> nombre de ficha en inglés (la usa la identificación por OCR). |
src-tauri/src/scryfall/nombres.rs |
Catálogo local de todos los nombres de carta y códigos de set (Indice, indice(), codigos_de_sets()). |
src-tauri/src/commands/cards.rs |
Comandos: resolve_decklist, job_cancel, card_autocomplete, card_search, card_prints, card_fetch, card_fetch_externa, deck_tokens_detect, sets_list, set_cards, import_archidekt. |
src-tauri/src/state.rs |
AppState.scryfall: Arc<Scryfall> (un cliente compartido, un limitador de ritmo compartido). |
Reglas documentadas en la cabecera del módulo e implementadas en Scryfall::enviar:
-
Límite de ritmo. Toda petición a
api.scryfall.comespera primero aLimitador::turno(): una marca de tiempo protegida por un mutex; quien llama duerme hasta que pasen al menos 100 ms (Duration::from_millis(100)enScryfall::new) desde la petición anterior. Un solo limitador para toda la app, así que los trabajos concurrentes comparten el presupuesto. -
Las imágenes son distintas. Las descargas (
CardApi::download) se saltan el limitador (con_ritmo = false) porque las imágenes de las cartas las sirve el CDN de Scryfall (*.scryfall.io), pero se limitan a 6 a la vez con un semáforo (DESCARGAS_A_LA_VEZ). -
Reintentos. El HTTP 429 y cualquier 5xx se reintentan hasta
MAX_REINTENTOS = 3veces, esperando 0,5 s, 1 s, 2 s, o la cabeceraRetry-After(en su forma de segundos) cuando está presente. Tras el último reintento: 429 ->ErrorCode::RateLimited; los demás fallos ->ErrorCode::Networkconestado. -
El 404 no es un error.
enviardevuelveNone;json()lo convierte enOk(None)y quienes llaman deciden. Por eso una búsqueda sin resultados (Scryfall responde 404) da una lista vacía, y por esocard()devuelveOption<ScryCard>. -
Tiempos de espera. 30 s en total, 10 s de conexión. User agent
ProxyBuilder/<version>. -
Registro de auditoría. Cada petición real se registra con
tracing(metodo,host,ruta,estado, mensaje «red»), de modo que se puede comprobar que abrir un mazo guardado no descarga nada. -
Punto de inyección para tests. El resolvedor depende del trait
CardApi(collection,card,card_lang,search,download), así que los tests usan un falso (Falsoen los tests deresolve.rs) en lugar de la red.
Método de Scryfall
|
Endpoint de Scryfall | Notas |
|---|---|---|
collection(ids) |
POST /cards/collection |
Cuerpo {identifiers: [...]} donde Identifier es Id, SetNumber, NameSet o Name (serializado sin etiqueta, untagged). Máximo 75 por llamada (LOTE). |
card(id) |
GET /cards/{id} |
None en el 404. |
card_lang(set, number, lang) |
GET /cards/{set}/{number}/{lang} |
Segmentos de ruta codificados con porcentaje (urlencode; los números de coleccionista pueden contener ★ o -). |
search(q, prints, limit) |
GET /cards/search |
prints = true añade unique=prints&include_multilingual=true. Sigue next_page hasta limit (limitado a TOPE_BUSQUEDA = 175). |
search_multilingual(q, limit) |
GET /cards/search |
Solo include_multilingual=true (un resultado por carta, en cualquier idioma); sin tope de 175. |
autocomplete(q) |
GET /cards/autocomplete?include_extras=true |
El comando ignora las consultas de menos de 2 caracteres. |
card_names() |
GET /catalog/card-names |
Alimenta el índice local de nombres. |
sets() |
GET /sets |
Explorador de sets y reconocimiento de códigos de set; se mapea a SetInfo. |
symbology() |
GET /symbology |
SVG de los símbolos de maná para el diseñador. |
download(url) |
cualquier URL de imagen | Solo bytes; quien llama los almacena. |
La app pasa el texto del usuario tal cual a la búsqueda de Scryfall, así que toda la sintaxis de Scryfall funciona en «Añadir carta» (t:goblin, set:neo, o:"draw a card"...). commands/cards.rs le añade:
-
consulta_busqueda:<q> lang:<code>cuando se elige un idioma distinto deany, másis:hirespara solo alta resolución. -
consulta_impresiones(variantes / impresiones):!"<nombre exacto>"+ los mismos filtros. Se quitan las comillas dobles del nombre para que no puedan cerrar la comilla antes de tiempo. -
consulta_set:e:<code>más unt:<type>opcional; ambos se filtran a alfanuméricos/letras para que el explorador de sets no pueda inyectar sintaxis de consulta adicional. - El flujo
identifyañadeinclude:extras -layout:art_series -layout:front_card(Scryfall oculta las fichas sininclude:extras; las cartas de arte y las cartas frontales de Jumpstart son ruido).
card_search y card_prints también añaden resultados del catálogo de fichas de Cockatrice cuando el idioma es en/sin definir y la opción de solo alta resolución está desactivada (véase Fuentes externas): card_search las pone después de los resultados de Scryfall, o primero si una se llama exactamente como la consulta y Scryfall no tiene ninguna; card_prints las añade al final. card_prints se traga los errores de búsqueda (unwrap_or_default) porque una ficha que Scryfall no tiene no es un fallo.
| Caché | Dónde | Duración | Propósito |
|---|---|---|---|
| Resultados de búsqueda | memoria, Busquedas de busquedas.rs
|
1 hora (VIDA_BUSQUEDA) |
Reabrir un diálogo o buscar la misma carta en varias listas no repite la petición. Clave = consulta + parámetros extra + límite. Acotada a cartas_segun_memoria() cartas (el 0,25 % de la RAM total / 4 KB por carta, limitado a 5 000..50 000); las entradas más antiguas se expulsan primero, y un resultado mayor que el tope no se almacena. Vida corta a propósito: los resultados pueden acabar en la caché persistente con la marca «ahora», y una entrada longeva haría que precios viejos parecieran recientes. |
| Datos de carta | tabla SQLite scryfall_cards (id, oracle_id, name, lang, set_code, collector_number, json, fetched_at; índices por nombre+idioma y por set+número+idioma), escrita por cache::guardar
|
TTL_MS = 7 días para los datos de juego; los precios los renueva aparte a las 24 h commands/stats.rs
|
Permite que las estadísticas, «vincular» y el diseñador funcionen sin conexión. La fila guarda el JSON completo de la carta. |
| Nombres / códigos de set | ficheros en app_cache_dir
|
7 días | Véase «Catálogo de nombres» más abajo. |
cache::leer_impresion encuentra una impresión por set + número + idioma (la de fetched_at más reciente). Los campos añadidos a ScryCard con el tiempo son Options donde None significa «guardada en la caché antes de que la app leyera este campo» (keywords, full_art, oversized); ScryCard::completa_para_disenar() y la comprobación de frescura de las estadísticas los usan para volver a pedir las filas viejas.
resolve(api, guardar, lista, opciones, cancelado, progreso) es genérico sobre CardApi y Guardar. Guardar es el punto de inyección de todo lo que no es Scryfall: guardar (almacenar los bytes de la imagen en el almacén de blobs; EnLaApp en commands/cards.rs llama a blobs.put_bytes), apuntar (escribir la carta en scryfall_cards), nombre_ingles (nombre en otro idioma -> inglés, mediante Fuentes externas), externa_por_nombre y externas_creadas_por (fichas de Cockatrice). Los valores por defecto no hacen nada, de modo que los tests pueden implementar solo guardar.
ResolveOptions { lang, image_policy, add_tokens }:
-
lang: un código de idioma de Scryfall (en,es...) oany/vacío para «el mejor disponible». -
ImagePolicy:BestAvailable(cualquier carta con una URI de imagen),WithImage(además rechazaimage_statusmissing/placeholder; el valor por defecto de la interfaz),HighresOnly(además exigehighres_image). -
add_tokens: añade también las fichas que crean las cartas.
flowchart TD
A["ParsedDecklist"] --> B["filtrar Card e included<br/>Peticion distintas (name, set, collector)"]
B --> C["1. POST /cards/collection<br/>lotes de 75, coincidencia por casa()"]
C --> D{"¿sin coincidencia y sin set?"}
D -- sí --> E["1b. nombre_ingles() máx. 20<br/>luego collection por nombre en inglés"]
D -- no --> F
E --> F["2-3. por cada carta encontrada"]
F --> G{"¿quiere otro idioma?"}
G -- sí --> H["en_idioma(): card_lang y luego search lang:xx"]
G -- no --> I
H --> I["segun_politica(): si no, buscar otra impresión"]
I -- ninguna --> U1["Unresolved NoImage"]
I -- ok --> J["finales (card, lang_fallback)"]
J --> K{"¿add_tokens?"}
K -- sí --> L["4. fichas_de() sobre las impresiones en inglés"]
K -- no --> M
L --> M["5. apuntar() a la caché<br/>descargar PNG por carta distinta"]
M --> N["6. construir copias de DeckCard en el orden de la lista"]
N --> O{"¿carta ausente en Scryfall?"}
O -- sí --> P["externa_por_nombre() Cockatrice"]
P -- ninguna --> U2["Unresolved NotFound"]
N --> Q["añadir fichas, luego fichas externas"]
Q --> R["ResolveResult { cards, unresolved }"]
-
Filtro de entrada. Solo se usan las líneas con
kind == Card && included. Las líneas se agrupan enPeticion { name, set, collector }distintas; las líneas repetidas se resuelven una vez y se copianqtyveces al final. -
Búsqueda. Cada
Peticionse convierte en unIdentifier: set + número ->SetNumber; solo set ->NameSet; si no,Name. Para los nombresA // Bsolo se envía la primera cara (nombre_para_buscar), porque/cards/collectionno encuentra el nombre completo de una carta de doble cara. Las peticiones van en lotes de 75. Las respuestas se emparejan conPeticion::casa(set y número sin distinguir mayúsculas, oScryCard::responde_a(name): nombre completo, nombre impreso o el nombre de cualquier cara) y nunca por posición, porque las entradasnot_founddesplazan el orden de la respuesta. Fase de progreso:Lookup. -
Nombres en otros idiomas (1b). Las peticiones que no encontraron nada y no tienen set pueden estar escritas en otro idioma («Muro de algas»). El idioma probado es
options.lang, o el español cuando está vacío, esanyoen. Para un máximo de 20 de esas líneas (MAX_TRADUCIDAS),Guardar::nombre_inglesse ejecuta de forma concurrente (el recurso en línea es lento); cada acierto se busca de nuevo por su nombre en inglés y se empareja conresponde_a. -
Idioma y política de imagen, por carta encontrada (fase de progreso
Language):- Si el usuario quiere un idioma y el
langde la carta es distinto,en_idiomapruebaGET /cards/{set}/{number}/{lang}y, si falta o está en otro idioma, busca!"name" lang:xxentre las impresiones, prefiriendo el mismo set y luego cualquiera. Si no existe nada, la carta se queda como está. -
segun_politicacomprueba la política. Si la carta no la cumple, se buscan todas las impresiones de ese nombre y se elige la mejor que la cumpla: mismo idioma y set, luego mismo idioma, luego cualquiera. Si ninguna la cumple, la petición esNoImage. - El indicador
lang_fallbackesquiere_idioma && final.lang != options.lang; pasa aCardMeta.lang_fallbacky se muestra como la insignia «vuelta a EN». - Para las fichas se recuerda la impresión original en inglés vista en el paso 1 (
inglesas), porque las impresiones traducidas llevanall_partsincompleto.
- Si el usuario quiere un idioma y el
-
Fichas (
add_tokens). A partir de la impresión en inglés de cada carta distinta,fichas_dedevuelve las fichas que crea (véase más abajo); se añaden al final del mazo comoCardSource::Token. -
Imágenes. Cada carta (y ficha) distinta se escribe en
scryfall_cards(apuntar) y luego se descarga en grupos de 12 conjoin_all(el semáforo del cliente mantiene la concurrencia real en 6).ScryCard::print_url(face)elige el PNG (745x1040) cuando existe y, si no,large; el origen se registra comoImageOrigin::ScryfallPngoScryfallLarge. Una carta de doble cara (is_dfc: sinimage_urisde nivel superior y dos caras con imagen) descarga también la cara 1 y pasa a serBackSpec::Dfc. Fase de progresoImages. -
Ensamblado, en el orden de la lista. Cada copia es una
DeckCardnueva (UUID nuevo,CardSource::Scryfall { scryfall_id },CardMetademeta_de). La sección de la línea fijamarca:Sideboard->Banquillo,Maybeboard->Opcional(véase Parseo de la lista del mazo). Una petición que Scryfall no encontró se prueba en Cockatrice por nombre (externa_por_nombre); si sigue sin aparecer queda comoUnresolved { line_no, name, reason: NotFound }. Una petición descartada por la política queda comoUnresolved ... NoImage. Siguen las fichas y después las fichas de otras fuentes que crean las cartas del mazo (externas_creadas_por, sin duplicados por nombre respecto a las fichas de Scryfall).
resolve_decklist devuelve un job_id de inmediato y se ejecuta en el runtime asíncrono de Tauri. El progreso sale por el evento resolve://progress (ResolveProgressEvent { jobId, progress: { phase, done, total } }, fases lookup, language, tokens, images) y el final por resolve://done (ResolveDoneEvent { jobId, result, error }). state.jobs (src-tauri/src/jobs.rs) reparte ids y un indicador de cancelación AtomicBool; job_cancel(jobId) lo activa y el resolvedor lo comprueba entre lotes (comprobar -> ErrorCode::Cancelled, en cuyo caso no se devuelve ninguna carta). El comando mantiene un guard de state.trabajo(), que hace que el actualizador automático se niegue a ejecutarse (Busy) mientras haya un trabajo en marcha.
El frontend usa lanzarTrabajo (src/lib/trabajos.ts), que escucha antes de lanzar (un trabajo corto puede terminar antes de que invoke devuelva su id) y almacena en un búfer los eventos tempranos. resolver() en src/features/decklist/acciones.ts construye las opciones a partir del store de la interfaz (lang, imagePolicy, addTokens), muestra las etiquetas de fase a partir de los eventos de progreso y trata Cancelled como «no ha cambiado nada». «Reaplicar idioma» (reaplicarIdioma) construye un ParsedDecklist sintético con una línea por cada carta de Scryfall no bloqueada (nombre + su set y número actuales) y llama al mismo flujo con addTokens: false; después cambia imágenes y metadatos conservando el id, las ediciones, el bloqueo y lo propio de cada carta (aplicarReaplicado en src/lib/cartas.ts).
-
card_prints(name, lang, highres_only)->Vec<CardSummary>: todas las impresiones de un nombre exacto (hasta 175), usado por el selector de variantes (variant-dialog.tsx) y por «Añadir carta» en su modo de nombre exacto (buscar(texto, exacto = true)enadd-card-dialog.tsx; en otro caso llama acard_search).lang: nullsignifica cualquier idioma. -
card_fetch(scryfall_id)->DeckCard(traer_carta): obtiene una impresión, la guarda en la caché, descarga su PNG (y la cara trasera) y devuelve una carta con origenTokensi sulayoutestoken/double_faced_token, yScryfallen otro caso. Quien llama la inserta o la usa para sustituir la imagen de otra carta. -
CardSummaryes la fila ligera para las rejillas: ids, nombres, set, número, una huella de miniatura (no una URL),highres,image_status,is_dfc,type_lineyfuentepara las cartas que no son de Scryfall. Miniaturas:resumir()registra cada URL de imagen bajo un SHA-256 de la URL enAppState.miniaturas(se vacía al pasar de 5 000 entradas) y la vista web pidepbimg://.../t/<huella>; el manejador del protocolo (src-tauri/src/protocol.rs) resuelve la huella, descarga (con el cliente de Scryfall parahttps://cards.scryfall.io/, y en otro caso conExterno, que tiene lista de permitidos) y guarda en caché el derivado. Véase Vista previa en vivo. -
sets_listyset_cards(code, type_filter)alimentan el Explorador de sets.
Se usa dos veces: «añadir fichas» al resolver, y «Detectar fichas» sobre un mazo existente (deck_tokens_detect, interfaz en src/features/decklist/fichas-dialog.tsx).
- Las fichas figuran en las entradas
all_partsde una carta concomponent == "token"(excluyendo la propia carta). -
Por qué solo impresiones en inglés: Scryfall ofrece
all_partscompleto solo en la impresión en inglés; las impresiones traducidas no lo tienen o lo tienen parcial. Así que, para cada carta que no esté en inglés,fichas_deobtiene primero su carta en inglés por nombre (de la cara frontal) mediante/cards/collectiony lee allí las partes. Si no se encuentra la carta en inglés, se siguen usando las partes de la propia carta traducida. - Después se piden los ids de las fichas en lotes de 75 por id. Dos fichas cuentan como la misma si su
clave_de_fichacoincide: el oracle id, oname|type_line|power/toughnesscuando no hay, de modo que la misma ficha de distintos sets de fichas aparece una sola vez. Cada resultado recuerda qué carta la creó (creada_por). -
faltan_en_el_deck(api, deck, de_la_cache, cancelado)quita además las fichas que el mazo ya tiene: el mismo id, la misma ficha de otro set o una ficha con el mismo nombre (también una carta propia con ese nombre). Las cartas salen de la caché local cuando es posible y de Scryfall en otro caso. Despuésdeck_tokens_detectañade también las fichas de Cockatrice que crean las cartas del mazo. Solo propone (FichaPropuesta { carta, creada_por }); el diálogo añade las elegidas concard_fetch.
Un índice local de todos los nombres de carta (unos 30 000 nombres en inglés de /catalog/card-names) y de todos los códigos de set (/sets), usado para reconocer el texto leído por OCR sin llamadas de red.
- Ficheros en
app_cache_dir:scryfall-card-names.json,scryfall-set-codes.json. Se renuevan cuando tienen más de 7 días; si la descarga falla se usa la copia vieja; la caché puede borrarse sin perder nada. Se cargan una vez por sesión enOnceCells (un fallo no se recuerda, así que se reintenta la próxima vez). -
Indicemantiene dos mapas con clavenormalizar(name)(minúsculas, sin acentos ni puntuación):exactosyplegados, donde se pliegan las letras que el OCR confunde (l,1,|->i;0->o;plegar). Los nombres de cartas de doble cara se indexan enteros y por cada cara. - Búsquedas:
exacto(line),al_principio(line)(el nombre más largo con el que empieza la línea, de dos palabras o más para que «Island of the dead» no sea «Island») yparecido(line)(la mejor coincidencia aproximada con similitud >= 0,85, recorriendo todo el catálogo y saltándose los candidatos cuya longitud difiere en más de un 15 %; es lenta, así que se usa para un puñado de líneas). - Consumidores:
commands/identify.rsyoriginales.rs(véase Identificación de cartas y OCR).
| Condición | Código | Dónde |
|---|---|---|
| Sin conexión, DNS, TLS, tiempo de espera |
Network (detalle) |
cualquier llamada |
| 429 tras 3 reintentos | RateLimited |
enviar |
| Otro no 2xx que no sea 404 (p. ej. 400 por una consulta incorrecta) |
Network (estado) |
enviar |
| Id de carta no encontrado |
NotFound (carta) |
card_fetch, card_link
|
| Trabajo cancelado | Cancelled |
resolve |
| Falla la escritura en la base de datos | Db |
cache::guardar |
| Fallos por línea durante la resolución | no es un error: entradas Unresolved en ResolveResult
|
resolve |
Todo resolve devuelve Err (y ninguna carta) si falla una petición de colección o una descarga de imagen; solo hay resultados parciales para los fallos a nivel de nombre.
-
src-tauri/src/scryfall/resolve.rs(mod tests, con la API falsaFalso): lista de cuatro cartas, marcas de banquillo, doble cara frontal/trasera, idioma de reserva, la política de alta resolución cambiando de impresión, fichas desde la impresión en inglés, fichas añadidas una sola vez, cancelación, más de 75 líneas en lotes, el progreso se completa, nombre en otro idioma mediante fuentes de reserva, reservas de Cockatrice. -
src-tauri/src/scryfall/{rate,busquedas,cache,fichas,nombres,fichas_auto,models}.rs: tiempos del limitador (reloj en pausa), expulsión y caducidad de la caché, ida y vuelta de la caché, tabla de tipos de ficha, índice de nombres aproximado/exacto, deduplicación de fichas, parseo de modelos (fixturefixtures/dusk-dawn-es.json). -
src-tauri/src/commands/cards.rs(mod tests): constructores de consultas, registro de miniaturas,traer_cartapara normal/DFC/ficha/sin imagen/ausente. - Los tests en vivo contra la API real están marcados
#[ignore](por ejemploscryfall_en_vivoenclient.rs).
- Un endpoint nuevo de Scryfall: añádelo a
Scryfall(usaself.json(...)para que se apliquen el límite de ritmo y los reintentos); si el resolvedor o los tests lo necesitan, añádelo aCardApiy a los falsos (Falsoenresolve.rs,Apien los tests decommands/cards.rs,SinRedencommands/stats.rs). - Un paso nuevo del flujo: respeta la regla «emparejar por identidad, nunca por posición», informa del progreso con una
ResolvePhasey llama acomprobar(cancelado)entre lotes de red. - Campos de carta nuevos: añádelos a
ScryCardcomoOption(para que el JSON antiguo de la caché siga deserializándose) y decide si hay que volver a pedir las filas viejas.
- Parseo de la lista del mazo, Fuentes externas, Identificación de cartas y OCR
- Añadir carta y variantes - los diálogos que usan la búsqueda, las impresiones y el autocompletado.
-
Almacenamiento y blobs - dónde viven las imágenes descargadas y
scryfall_cards. - Estadísticas - consumidor de la caché de cartas y de la renovación de precios cada 24 h.
- IPC y manejo de errores, Capa de aplicación Rust
Use and build · Uso y desarrollo
- User-Guide · Guía de usuario
- Development-Setup · Preparación del entorno de desarrollo
- Testing-and-CI · Tests y CI
- Releases-and-Auto-Updates · Versiones y actualizaciones automáticas
- Conventions · Convenciones
Architecture · Arquitectura
- Architecture · Arquitectura
- IPC-and-Error-Handling · IPC y manejo de errores
- Rust-App-Layer · Capa de aplicación Rust
Data · Datos
- Deck-Model · Modelo del mazo
- Storage-and-Blobs · Almacenamiento y blobs
- Deck-Package-Format · Formato del paquete de mazo
- Deck-Library · Biblioteca de mazos
Getting cards · Conseguir cartas
- Decklist-Parsing · Parseo de la lista del mazo
- Scryfall-Integration · Integración con Scryfall
- External-Sources · Fuentes externas
- Card-Identification-and-OCR · Identificación de cartas y OCR
Layout, images, PDF · Maquetación, imagen y PDF
- Layout-Engine · Motor de maquetación
- Imaging-and-PDF · Imagen y PDF
- Export · Exportación
- Live-Preview · Vista previa en vivo
- Statistics · Estadísticas
Card designer · Diseñador de cartas
- Designer-Overview · Visión general del diseñador
- Designer-Engine · Motor del diseñador
- Designer-Composition · Composición del diseñador
- Frame-Packs · Packs de marcos
- Designer-App-Layer · Capa de aplicación del diseñador
- Designer-UI · Interfaz del diseñador
- Card-Editor-Dialog · Diálogo Editar carta
Game table · Mesa de juego
Frontend · Frontend
- Frontend-Architecture · Arquitectura del frontend
- State-Stores · Stores de estado
- Internationalization · Internacionalización
- Themes-and-Skins · Temas y skins
- Settings-and-Shell · Ajustes y shell
- Tutorials · Tutoriales
- Decklist-Panel · Panel de la lista del mazo
- Add-Card-and-Variants · Añadir carta y variantes
- Set-Browser · Explorador de sets
Reference · Referencia