Skip to content

Add variant picker landing screen and multi-variant deck support#2

Open
patrickhammond wants to merge 13 commits into
mainfrom
claude/spec-kit-presentation-planning-ljgmfj
Open

Add variant picker landing screen and multi-variant deck support#2
patrickhammond wants to merge 13 commits into
mainfrom
claude/spec-kit-presentation-planning-ljgmfj

Conversation

@patrickhammond

Copy link
Copy Markdown
Owner

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)

  • Added 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.
  • Refactored src/slides/SlideShow.jsx: Slides are now pure components registered in SLIDE_REGISTRY by 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.
  • Updated 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

  • Added 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>.
  • Added src/picker/VariantPicker.test.jsx: Accessibility tests (axe) and interaction tests for the picker.
  • Extended src/index.css: Styles for picker grid layout, variant cards, and responsive sizing.

Spec Kit Integration

  • Initialized Spec Kit project structure (.specify/ directory) with:
    • Common bash functions (common.sh) for feature management
    • Feature creation script (create-new-feature.sh)
    • Prerequisite checking and setup scripts
    • Claude AI skills for the full SDD workflow (specify, plan, tasks, implement, clarify, checklist, analyze, constitution)
    • Templates for spec, plan, tasks, and checklist artifacts
    • Extension system for agent context management
    • Workflow definitions for the full SDD cycle
  • Added docs/constitution.md: Project principles (styling in CSS, no inline styles; variant-aware copy; accessibility-first design)
  • Created example feature specs/001-variant-picker/ with complete spec, plan, tasks, research, data model, and contracts

Documentation & Configuration

  • Added docs/audience*.md: Audience profiles for gdg (primary), ingage (archived), and client (template) variants
  • Added AGENTS.md: Agent-agnostic context for any coding agent
  • Updated CLAUDE.md: Reflects multi-variant architecture and variant picker feature
  • Updated docs/tech-stack.md: Documents new variant data model and picker component
  • Added docs/demo.md: Runbook for live demo of Spec Kit on this repo
  • Updated docs/audience.md: Index of audience profiles per variant

Testing

  • Added src/App.resolve.test.jsx: Tests URL-to-variant resolution and picker/deck mode switching
  • Updated tests/a11y.spec.js: Mirrors ingage variant slide slugs for accessibility testing
  • Updated src/slides/SlideShow.test.jsx: Tests against new SLIDE_REGISTRY structure

Notable Implementation Details

  • No inline styles: All variant-specific sizing and colors live in CSS; per-variant copy is passed as props, not hardcoded in JSX.
  • Automatic section numbering: The manifest supplies slide order; withSections() derives section counters, so reordering slides auto-renumbers without manual edits.
  • Graceful fallback: Unknown or missing ?variant= parameters show the picker, making bad links recoverable rather than silently defaulting.
  • Spec Kit as dogfooding: The variant picker feature itself is fully specified in Spec Kit format (spec.md, plan.md, tasks.md, etc.), demonstrating the workflow on the talk's own codebase.

https://claude.ai/code/session_01468czqpkhiBJY7v812KmgB

claude added 13 commits June 15, 2026 22:56
- 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
@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
presentation-spec-kit 7420a9d Jun 16 2026, 11:17 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants