Add variant picker landing screen and multi-variant deck support#2
Open
patrickhammond wants to merge 13 commits into
Open
Add variant picker landing screen and multi-variant deck support#2patrickhammond wants to merge 13 commits into
patrickhammond wants to merge 13 commits into
Conversation
- Split audience.md into an index + per-variant profiles (gdg, ingage, client) so each talk can be refined independently off main - Add GDG Cincinnati profile as the new primary target (40 min, all-dev community, live demo centerpiece, conceptual slides) - Preserve the delivered Ingage lightning talk profile verbatim - Add AGENTS.md for agent-agnostic context (Copilot/Cursor/Gemini) - Add docs/constitution.md encoding house rules as Spec Kit principles, to be mirrored into .specify/memory/constitution.md on init https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
Behavior-preserving: the ingage variant renders the same 9-slide arc as before. - src/data/variants.js: per-variant deck manifest (ordered entries: slides with id/slug/section/props, plus the flow as an entry). Single source of truth for slide order, section numbers, and slugs. resolveVariant + DEFAULT_VARIANT. - src/slides/SlideShow.jsx: slides become a SLIDE_REGISTRY keyed by id; section numbers come from a prop (vary per variant), and per-variant copy (title byline, close) is prop-driven. Removed the index-based default export. - src/App.jsx: reads ?variant= at load, renders the active variant's manifest; the flow is now just an entry, removing FLOW_SLIDE_INDEX special-casing. Nav, hash deep-linking, and dots all iterate entries generically. - Tests updated to render every slide across all variants from the manifest (73 passing). Lint and build green for changed files. - Synced CLAUDE.md, docs/tech-stack.md, docs/speaker-notes.md to the new model. Both ingage and gdg currently share the base arc; gdg diverges in the content pass. A variant picker (no default) is reserved as the live-demo feature. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
- specify init --here --integration claude: adds .specify/ (templates, memory, workflows) and .claude/skills/speckit-* slash commands - Populate .specify/memory/constitution.md with this repo's real house rules (mirrors docs/constitution.md), so the demo can show the constitution enforcing house style on agent-written code - Init appended a managed SPECKIT agent-context marker to CLAUDE.md (kept) This makes the repo demo-ready for the meta demo: /speckit.specify, .plan, .tasks, .implement now work against this very codebase. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
specs/001-variant-picker/spec.md + requirements checklist, generated via the /speckit.specify workflow. Feature: replace the silent default-variant fallback with a picker landing screen when no (or an unknown) variant is specified; preserve direct deep-linking for valid variants. Demo artifact: lives on the claude/demo-variant-picker safety branch so the working branch stays clean for a live re-derivation. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
specs/001-variant-picker/: plan.md, research.md, data-model.md, quickstart.md, contracts/url-variant-contract.md. Constitution Check passes (no inline styles, one source of truth, data-driven from the manifest). Updated CLAUDE.md SPECKIT marker to reference the plan. Approach: extend variants.js with display metadata (room/length/demo); add a src/picker/VariantPicker component (styled in index.css); change App.jsx resolution so no/unknown variant -> picker mode instead of silent default. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
specs/001-variant-picker/tasks.md: 16 tasks organized by user story (US1 picker + select = MVP, US2 deep-link no-regression, US3 unknown -> picker), with foundational variant-metadata + resolution plumbing and a polish phase. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
All tasks T001-T016 complete (T015 Playwright e2e deferred: browser binaries not installable in this environment). - src/data/variants.js: add per-variant meta (room/length/demo) + isKnownVariant - src/picker/VariantPicker.jsx: data-driven picker listing every variant - src/App.jsx: split into picker-mode vs Deck; no/unknown variant -> picker (no silent default); known -> deck with hash deep-link preserved; 'Pick a talk' control returns to the picker - src/index.css: .picker-* and .deck-to-picker styles (vmin, brand, a11y) - tests: VariantPicker.test.jsx + App.resolve.test.jsx (84 tests pass total) - docs/tech-stack.md + variants.js header synced Verification: changed/new files lint clean (3 remaining lint errors are pre-existing in playwright.config.js and SpecKitFlow.jsx); npm test 84/84 green; npm run build succeeds; rendered-copy audit clean. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
The gdg arc becomes a ~40-min superset of the lightning arc:
- New slides (src/slides/SlideShow.jsx): WhoAmISlide (unnumbered intro,
placeholder copy), DemoSlide ('Time for a Demo' transition, the live meta-demo
centerpiece), LessonsSlide ('What I've Learned' practitioner beat)
- src/data/variants.js: split into ingageArc (unchanged, sections 1-8) and a new
gdgArc (sections 1-10) with the three new slides, a community close, and the
'you' title byline. Per-variant copy passed as plain-string props
(taglineLines, inviteLines) so no JSX lives in the data module
- TitleSlide/WhatsNextSlide take plain-data props for per-variant copy
- Docs: CLAUDE.md gdg arc note; speaker-notes.md GDG delivery addendum
(40-min budget + per-slide guidance)
ingage variant untouched. Lint clean (changed files), 85 unit tests pass
(new gdg slides covered by the manifest sweep), build green.
https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
Stage choreography for the GDG meta-demo: build the variant picker live on this repo, safety-netted by the claude/demo-variant-picker branch. - Two-path model (run clean vs git switch to the finished branch) - Pre-flight checklist, live-vs-pre-built risk split, timed ~12-15 min script - Constitution Check / analyze as the load-bearing teaching beat - Escape hatches and a reset-to-clean procedure - Link demo.md from the GDG audience profile https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
- src/data/variants.js: real who-am-I copy (name, role, three GDG-relevant bullets) + photo; community close (GDG Cincinnati / Ohio DevFest), replacing the placeholder handle - src/slides/SlideShow.jsx: WhoAmISlide gains optional photo/photoAlt (circular headshot beside the intro text) - public/img/patrick-hammond.jpg: headshot cropped to a 600x600 square - src/index.css: .whoami row layout + circular .whoami-photo Lint clean, 85 tests pass (photo alt-text covered), build green (image in dist/). https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
Brings the picker feature + its full Spec Kit artifact trail together with the GDG content, so both ship from one branch and can be cherry-picked. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB # Conflicts: # CLAUDE.md # src/data/variants.js # src/index.css
Review items:
1. e2e (tests/a11y.spec.js): pin ?variant=ingage on every nav (no variant now
shows the picker) and update stale slugs + flow hash (#spec-kit-flow).
2. Hide the 'Pick a talk' button on the flow, where it collided with the
top-left section label.
3. selectVariant navigates to path+query (no fragment) so a stale picker hash
is dropped and the deck opens at the title.
4. WhatsNext: empty inviteLines now falls back to the default invite (was a
truthy [] rendering a blank close). Added a regression test.
5. parseHash guards flowIndex === -1 for a future flow-less variant.
Pre-existing:
- Flow Esc/Home now returns to the overview only (per CLAUDE.md) and calls
preventDefault; it no longer advances the deck, so Esc-to-exit-fullscreen
doesn't also jump slides.
- Dot aria-labels match the printed section ('Section 6') instead of array
index ('Slide 8').
Lint clean, 97 unit tests pass, build green.
https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
#6 variants.js: shared entries (creed/hook/sdd/specKit/flow/why/honestClose/ whereToStart) are defined once and composed per arc; section counters are derived from position by withSections (mark cold-opens numbered:false) instead of hand-written literals. Auto-numbering reproduces the prior sections exactly (ingage 1-8, gdg 1-10); withSections clones so shared consts aren't mutated. #7 App.jsx: variant is now React state. Selecting/leaving the picker pushState's a shareable URL and updates state instead of forcing a full page reload (no bundle re-download or flow re-init mid-talk); a popstate listener handles back/forward; the Deck is keyed on the variant so it remounts to the title on switch. Deck takes an onExit prop for the 'Pick a talk' control. docs/tech-stack.md updated. Lint clean, 97 tests pass, build green. https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB
Contributor
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
presentation-spec-kit | 7420a9d | Jun 16 2026, 11:17 PM |
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.
Summary
Refactors the talk deck to support multiple presentation variants (gdg, ingage, client) delivered from a single codebase, and adds a variant picker landing screen shown when no variant is specified. This enables the same talk to be customized per audience without code duplication.
Key Changes
Variant Architecture (Architecture C)
src/data/variants.js: Per-variant deck manifest defining slide order, section numbering, and copy variations. Each variant is a list of slide entries (with optional props for per-variant text) plus the interactive flow block, all indexed by variant slug.src/slides/SlideShow.jsx: Slides are now pure components registered inSLIDE_REGISTRYby id, with per-variant copy passed as props (e.g.,taglineLines,byline). Section counters are derived from position, not hardcoded, so inserting/reordering slides auto-renumbers the rest.src/App.jsx: Replaced hash-based slide navigation with URL query parameter (?variant=) for variant selection. When no variant or an unknown one is given, shows the picker; otherwise loads the selected variant's slide sequence.Variant Picker UI
src/picker/VariantPicker.jsx: Landing screen listing all available variants with name, audience, length, and demo indicator. Clicking a variant navigates to the deck with?variant=<slug>.src/picker/VariantPicker.test.jsx: Accessibility tests (axe) and interaction tests for the picker.src/index.css: Styles for picker grid layout, variant cards, and responsive sizing.Spec Kit Integration
.specify/directory) with:common.sh) for feature managementcreate-new-feature.sh)docs/constitution.md: Project principles (styling in CSS, no inline styles; variant-aware copy; accessibility-first design)specs/001-variant-picker/with complete spec, plan, tasks, research, data model, and contractsDocumentation & Configuration
docs/audience*.md: Audience profiles for gdg (primary), ingage (archived), and client (template) variantsAGENTS.md: Agent-agnostic context for any coding agentCLAUDE.md: Reflects multi-variant architecture and variant picker featuredocs/tech-stack.md: Documents new variant data model and picker componentdocs/demo.md: Runbook for live demo of Spec Kit on this repodocs/audience.md: Index of audience profiles per variantTesting
src/App.resolve.test.jsx: Tests URL-to-variant resolution and picker/deck mode switchingtests/a11y.spec.js: Mirrors ingage variant slide slugs for accessibility testingsrc/slides/SlideShow.test.jsx: Tests against newSLIDE_REGISTRYstructureNotable Implementation Details
withSections()derives section counters, so reordering slides auto-renumbers without manual edits.?variant=parameters show the picker, making bad links recoverable rather than silently defaulting.https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB