Repository navigation
Decks: first-class deck abstraction + URL structure (#55) - #64
Merged
Merged
Conversation
Introduce a Deck concept (metadata + presentation hints + a resolved
QuestionSet) and a registry/resolver so /play and the hajnalig event page
draw questions through a deck instead of importing questions.json directly.
- src/data/decks/: Deck/ResolvedDeck types, library + hajnalig decks, and
getDeck(slug)/getAllDecks resolver. Library deck references the global
pool by id (no text duplication); hajnalig carries its own inline set
(its questions are not a subset of the global pool).
- play.astro consumes the library deck; new SSR /play/[deck] serves any
deck at a stable path with per-question OG preserved. Library redirects
to /play for back-compat; unknown slugs fall back to /play.
- hajnalig wrapper resolves its deck via getDeck('hajnalig').
No behavior change for existing pages. Build + e2e green.
✅ Deploy Preview for whocards-calmly ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Closes #55
What
Introduces a first-class Deck abstraction = metadata + presentation hints + a curated, ordered set of question references.
/play, the new/play/[deck]route, and the hajnalig event page all now resolve their questions through a deck via a registry, instead of importingquestions.jsondirectly. No behavior change for existing pages.This is foundational — it unblocks #57 (AI Check-In: wire the deck into /play) and the custom-decks half of #45.
Deck model (
src/data/decks/)types.ts—Deck(authored),ResolvedDeck(with a concreteQuestionSet),DeckPresentation,DeckSource.library.ts— the full WhoCards library;source: {kind: 'library'}references the global pool by id (no text duplicated). Keeps the legacy hero bg + white text.hajnalig.ts—source: {kind: 'inline', questions}. The hajnalig set (163 q's, hu/en) is not a subset of the global pool (66 q's) and its text differs even for shared ids, so it carries its own questions inline. The model supports both reference-by-id and inline so future decks can do either.index.ts— registry + resolver:getDeck(slug): ResolvedDeck | undefined— metadata + presentation + resolvedQuestionSet.getAllDecks(): ResolvedDeck[],isDeckSlug(slug),DEFAULT_DECK_SLUG.A deck carries the presentation/config hints
<Play>/Layoutalready use:languages,questionClassName,oldBg,languageStorageKey,userIdStorageKey, optionaltracking. Pages just spread them through, so<Play>itself was unchanged.URL decision
Decision: deck → path segment, lang + question → query params.
/play/[deck]. A deck is a marketable / linkable / ad-targetable entity, so it deserves a stable, SEO-friendly URL and its own OG share card. Kept inside the existing/playfamily rather than a new/decks/*tree so it shares the SSR play machinery./playfor back-compat./play/library301-redirects to/play(in-pageAstro.redirect) so there's no duplicate URL for the same content.?lang=,?q=) — ephemeral view-state, and this preserves the SSR-for-OG mechanism already inplay.astro/Head.astro. Crawlers (no JS) hit the SSR page and get per-questionog:image(/og/{lang}/{id}.png); with no?q=they get the deck's own title/description card./play/[deck]is SSR (prerender = false), resolving the deck and emitting per-question OG via the existing Headid/languageprops. Unknown slugs fall back to/play(302).Redirect implications (
netlify.toml)No
netlify.tomlchange was needed and nothing was broken:/:language/question/:id → /play?lang=:language&q=:id(301) redirect is untouched./play?lang=&q=continues to work exactly as before./play/library → /play) is handled in-page viaAstro.redirect, keeping all path/back-compat logic colocated with the route rather than split intonetlify.toml. Future decks need no redirect entries — they're served directly by the SSR/play/[deck]function.Public interface (for #57)
To add the AI Check-In deck (#57): drop an
ai-at-work.tsdeck intosrc/data/decks/, register it inindex.ts, and it's instantly playable at/play/ai-at-workwith OG resolving.Verification
pnpm build— green (SSR/playand/play/[deck]functions emitted).pnpm test(Playwright e2e) — 18 passed, 3 skipped (pre-existing skips: contact form needs a backend; SSR-OG test needs a functions-capable server). The hajnalig event-play suite exercises the deck refactor and stays green.tsc— the deck/play files are type-clean. (Remaining repo-wide tsc errors are pre-existing and in untouched files:.astromodule typings without@astrojs/check, and third-partysatori/bidi-js/wawoff2typings.)