The work focuses on turning the Cornucopia card pipeline into a generic, data-driven system so new decks and updated deck versions can be added with minimal manual effort. The goal is to let contributors drop in the required YAML, card content, styling, and image assets, and have the Svelte site automatically discover, load, and present the deck as a browsable experience at https://cornucopia.owasp.org/cards.
Today, parts of the loading pipeline are already convention-based, especially for mappings, styling, and card-image YAML files. The remaining effort is to remove the last hard-coded edition registrations, static card lists, and per-deck UI assumptions so deck discovery, routing, rendering, and browsing all derive directly from deck metadata. Once that is done, importing a new deck or updating an existing one becomes a repeatable content operation rather than an application code change.
Deck discovery should be configurable for convenience and security. Instead of always scanning all matching files under source, discovery should support a controlled configuration layer that defines which directories, file patterns, editions, versions, and asset roots are allowed. This makes it easier to work with draft decks, test decks, and partial imports during development, while also reducing the risk of unintentionally exposing unreviewed or malformed content in production. A configurable allowlist or manifest-based discovery model would give maintainers explicit control over what the site may load, without giving up the long-term goal of automatic deck onboarding.
-
Deck discovery must stop being hard-coded in cornucopia.owasp.org/src/lib/services/deckService.ts. Today the app only knows decks from the static latests and decks arrays.
A new YAML in source is invisible until this registry is updated.
-
Suit discovery must stop being hard-coded in cornucopia.owasp.org/src/domain/suit/suitController.ts.
That file keeps its own fixed deck/version list and language map, separate from DeckService, so even if DeckService were made dynamic this controller would still block the new deck.
-
The card aggregation routes still enumerate specific editions in cornucopia.owasp.org/src/routes/cards/+page.server.ts and cornucopia.owasp.org/src/routes/cards/[card]/+page.server.ts.
Those pages manually merge mobileapp, webapp, companion, and eop. They need to iterate over discovered editions instead.
-
The edition browser UI is hard-coded for four decks in cornucopia.owasp.org/src/routes/edition/[edition]/+page.svelte.
It has fixed deck buttons, fixed per-deck intro text, and fixed default preview cards (PC2, VE2, AAI2, SP2). For generic onboarding, that page needs deck metadata from YAML, not per-edition branches in Svelte. Unknown editions and cards should still result in a proper 404.
-
Card detail rendering still has edition-specific component registration in cornucopia.owasp.org/src/lib/components/cardFound.svelte and cornucopia.owasp.org/src/lib/components/cardPreview.svelte.
cardFound chooses taxonomy components from a fixed map, and cardPreview only registers an edition-specific mapping component for eop. If a new deck needs taxonomy/mapping rendering, there is no generic fallback config yet.
-
Unknown card IDs are currently rejected by a static allowlist in cornucopia.owasp.org/src/domain/card/cardIds.ts, and that gate is used by cornucopia.owasp.org/src/routes/cards/[card]/+page.svelte plus the edition card pages.
That has to be removed in favor of “card exists in loaded deck data” else 404.
-
Suit and card ordering are not generic in cornucopia.owasp.org/src/domain/suit/order.ts and cornucopia.owasp.org/src/domain/card/order.ts.
A new deck with new suit names or new card IDs will fall outside those maps. Ordering should come from YAML order, or from explicit metadata in the yaml configuration.
-
Source YAML plus images is still not enough by itself, because DeckService also expects scaffolded content folders under cornucopia.owasp.org/data/cards.
See cornucopia.owasp.org/src/lib/services/deckService.ts: it loads the deck from source/...cards...yaml, but then reads technical-note.md and explanation.md from data/cards/-cards--. The scaffolding step is still part of the runtime content model which means that it should be part of the build. If scaffolding already exist for all ready decks, than the scaffolding should do nothing.
-
Image serving is not actually “drop images into source and they work”.
The image YAML uses literal public URLs like the ones in source/eop-card-images-5.0.yaml, and cornucopia.owasp.org/src/lib/components/cardPreview.svelte just uses that URL directly. There is no source-folder image discovery or asset copy pipeline here. The images still need to exist at a served web path, typically under static. Ensure image assets and yaml assets are bundled together and picked up by the scaffolding to ensure they become available later when the the card browser is loaded.
-
Deck naming and human-readable labels are still hard-coded in cornucopia.owasp.org/src/lib/services/deckServiceConsts.ts and in the page title helper inside cornucopia.owasp.org/src/routes/cards/[card]/+page.svelte.
A generic system needs edition display name, description, maybe preview card, and whether it is “external” to come from metadata.
The work focuses on turning the Cornucopia card pipeline into a generic, data-driven system so new decks and updated deck versions can be added with minimal manual effort. The goal is to let contributors drop in the required YAML, card content, styling, and image assets, and have the Svelte site automatically discover, load, and present the deck as a browsable experience at https://cornucopia.owasp.org/cards.
Today, parts of the loading pipeline are already convention-based, especially for mappings, styling, and card-image YAML files. The remaining effort is to remove the last hard-coded edition registrations, static card lists, and per-deck UI assumptions so deck discovery, routing, rendering, and browsing all derive directly from deck metadata. Once that is done, importing a new deck or updating an existing one becomes a repeatable content operation rather than an application code change.
Deck discovery should be configurable for convenience and security. Instead of always scanning all matching files under source, discovery should support a controlled configuration layer that defines which directories, file patterns, editions, versions, and asset roots are allowed. This makes it easier to work with draft decks, test decks, and partial imports during development, while also reducing the risk of unintentionally exposing unreviewed or malformed content in production. A configurable allowlist or manifest-based discovery model would give maintainers explicit control over what the site may load, without giving up the long-term goal of automatic deck onboarding.
Deck discovery must stop being hard-coded in cornucopia.owasp.org/src/lib/services/deckService.ts. Today the app only knows decks from the static latests and decks arrays.
A new YAML in source is invisible until this registry is updated.
Suit discovery must stop being hard-coded in cornucopia.owasp.org/src/domain/suit/suitController.ts.
That file keeps its own fixed deck/version list and language map, separate from DeckService, so even if DeckService were made dynamic this controller would still block the new deck.
The card aggregation routes still enumerate specific editions in cornucopia.owasp.org/src/routes/cards/+page.server.ts and cornucopia.owasp.org/src/routes/cards/[card]/+page.server.ts.
Those pages manually merge mobileapp, webapp, companion, and eop. They need to iterate over discovered editions instead.
The edition browser UI is hard-coded for four decks in cornucopia.owasp.org/src/routes/edition/[edition]/+page.svelte.
It has fixed deck buttons, fixed per-deck intro text, and fixed default preview cards (PC2, VE2, AAI2, SP2). For generic onboarding, that page needs deck metadata from YAML, not per-edition branches in Svelte. Unknown editions and cards should still result in a proper 404.
Card detail rendering still has edition-specific component registration in cornucopia.owasp.org/src/lib/components/cardFound.svelte and cornucopia.owasp.org/src/lib/components/cardPreview.svelte.
cardFound chooses taxonomy components from a fixed map, and cardPreview only registers an edition-specific mapping component for eop. If a new deck needs taxonomy/mapping rendering, there is no generic fallback config yet.
Unknown card IDs are currently rejected by a static allowlist in cornucopia.owasp.org/src/domain/card/cardIds.ts, and that gate is used by cornucopia.owasp.org/src/routes/cards/[card]/+page.svelte plus the edition card pages.
That has to be removed in favor of “card exists in loaded deck data” else 404.
Suit and card ordering are not generic in cornucopia.owasp.org/src/domain/suit/order.ts and cornucopia.owasp.org/src/domain/card/order.ts.
A new deck with new suit names or new card IDs will fall outside those maps. Ordering should come from YAML order, or from explicit metadata in the yaml configuration.
Source YAML plus images is still not enough by itself, because DeckService also expects scaffolded content folders under cornucopia.owasp.org/data/cards.
See cornucopia.owasp.org/src/lib/services/deckService.ts: it loads the deck from source/...cards...yaml, but then reads technical-note.md and explanation.md from data/cards/-cards--. The scaffolding step is still part of the runtime content model which means that it should be part of the build. If scaffolding already exist for all ready decks, than the scaffolding should do nothing.
Image serving is not actually “drop images into source and they work”.
The image YAML uses literal public URLs like the ones in source/eop-card-images-5.0.yaml, and cornucopia.owasp.org/src/lib/components/cardPreview.svelte just uses that URL directly. There is no source-folder image discovery or asset copy pipeline here. The images still need to exist at a served web path, typically under static. Ensure image assets and yaml assets are bundled together and picked up by the scaffolding to ensure they become available later when the the card browser is loaded.
Deck naming and human-readable labels are still hard-coded in cornucopia.owasp.org/src/lib/services/deckServiceConsts.ts and in the page title helper inside cornucopia.owasp.org/src/routes/cards/[card]/+page.svelte.
A generic system needs edition display name, description, maybe preview card, and whether it is “external” to come from metadata.