Skip to content

Phase 1: rendering reliability and accessibility - #2

Merged
fmadore merged 7 commits into
mainfrom
claude/roadmap-repo-review-kmefjm
Jul 10, 2026
Merged

Phase 1: rendering reliability and accessibility#2
fmadore merged 7 commits into
mainfrom
claude/roadmap-repo-review-kmefjm

Conversation

@fmadore

@fmadore fmadore commented Jul 10, 2026

Copy link
Copy Markdown
Owner
  • Keep the fixed 1280×720 scaled canvas on narrow screens
    (scrollActivationWidth: null) instead of reveal 6's scroll view,
    which clipped two-column slides on portrait phones.
  • Reserve a real strip for a compact footer on shallow screens
    (max-height 560px) so the footer can no longer cover slide content;
    desktop rendering is unchanged.
  • Make the image lightbox fully keyboard-accessible: zoomable images
    are focusable controls (Enter/Space opens), the dialog focuses its
    close button, traps Tab, keeps arrow-key navigation and
    Escape-to-close, restores focus on close, and mirrors its visual
    state with inert/aria-hidden. French strings added.
  • Fix TOC modal semantics and behaviour: entries wrapped in
  • ,
    focus moves into the dialog and is restored on close, arrow keys
    move between entries instead of driving the deck, aria-current
    marks the active entry, unused data-toc-part removed.
  • Promote stable per-talk components (.byline .role, .byline.authors,
    .author-logo, .demo-wrap/.demo-shot) into shared/theme.css and slim
    the per-deck style blocks; remove the dead .shot-todo component.
  • Fit engine: measure horizontal overflow too, keep centred layouts
    centred when fitted, expose the applied scale as data-fit, warn
    below 0.95 and stamp data-fit-fail below 0.90 (data-fit-allow opts
    out), re-fit after late-loading media, ?no-fit/?audit disables
    fitting; ?check now shows the fit scale.
  • Generic file embeds (data-embed-src, data-source-url,
    data-error-message) with accessible loading/failure states.
  • Centralise live-iframe lazy-loading + offline fallback in deck.js.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er

claude added 7 commits July 10, 2026 09:43
- Keep the fixed 1280×720 scaled canvas on narrow screens
  (scrollActivationWidth: null) instead of reveal 6's scroll view,
  which clipped two-column slides on portrait phones.
- Reserve a real strip for a compact footer on shallow screens
  (max-height 560px) so the footer can no longer cover slide content;
  desktop rendering is unchanged.
- Make the image lightbox fully keyboard-accessible: zoomable images
  are focusable controls (Enter/Space opens), the dialog focuses its
  close button, traps Tab, keeps arrow-key navigation and
  Escape-to-close, restores focus on close, and mirrors its visual
  state with inert/aria-hidden. French strings added.
- Fix TOC modal semantics and behaviour: entries wrapped in <li>,
  focus moves into the dialog and is restored on close, arrow keys
  move between entries instead of driving the deck, aria-current
  marks the active entry, unused data-toc-part removed.
- Promote stable per-talk components (.byline .role, .byline.authors,
  .author-logo, .demo-wrap/.demo-shot) into shared/theme.css and slim
  the per-deck style blocks; remove the dead .shot-todo component.
- Fit engine: measure horizontal overflow too, keep centred layouts
  centred when fitted, expose the applied scale as data-fit, warn
  below 0.95 and stamp data-fit-fail below 0.90 (data-fit-allow opts
  out), re-fit after late-loading media, ?no-fit/?audit disables
  fitting; ?check now shows the fit scale.
- Generic file embeds (data-embed-src, data-source-url,
  data-error-message) with accessible loading/failure states.
- Centralise live-iframe lazy-loading + offline fallback in deck.js.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
- talks/talks.json: structured manifest of published talks (slug, date,
  language, event, venue, titles, description, presenters, tags).
- tools/build-index.py: render the landing page's talk list statically
  from the manifest (works without JavaScript), embed a JSON copy for
  the client-side enhancement, and verify sync with --check.
- index.html: static talk list between generated markers, per-talk
  extras row (presenters, language, PDF, offline copy), search and
  language/year/topic filters with the state mirrored in the URL,
  static footer links, canonical URL and Open Graph metadata.
- tools/audit.py: one-command repository audit — missing local assets,
  duplicate ids, missing alt/iframe titles, _blank links without
  noopener, manifest/folder/landing-page sync, stale placeholders and
  placeholder QR codes, orphaned and duplicate assets, and (with
  --site) notes-free publication builds. Non-zero exit on failure.
- tools/browser-check.mjs: Playwright checks for every deck at
  1280×720, 844×390 and 390×844 — console errors, auto-fit failures,
  raw overflow, footer overlap, scroll-view regression — plus
  representative template screenshots for visual regression.
- tools/visual-diff.mjs: tolerant screenshot comparison (pixelmatch),
  failure diffs written for CI artifacts, nothing committed.
- Rhodes deck: real QR code (was the template placeholder) and the
  restored cover QR block; resolved the remaining TODO.
- Existing dense slides carry an explicit data-fit-allow so the new
  below-0.90 fit gate documents them instead of silently passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
- tools/strip-notes.py rebuilt: publishes from an explicit allowlist
  (index.html, CNAME, .nojekyll, shared/, non-underscored talks/)
  instead of copying the whole repo; strips <aside class=notes> in any
  quoting/class-order/case/multiline form; removes the reveal notes
  plugin tag and never copies the plugin file; refuses a destination
  that contains the source; counters are per-build; asserts the
  finished artifact is notes-free. tools/test_strip_notes.py covers
  all of it (13 tests).
- Slim syntax highlighting: fetch-highlight.py pinned to highlight.js
  11.11.1 with a CDN fallback, node --check verification and a
  provenance record in shared/vendor-manifest.json (also records the
  vendored reveal.js 6.0.1). shared/highlight.min.js (40 KB) replaces
  the 921 KB bundled plugin, which is deleted; decks with code load
  the slim build, decks without code load nothing.
- Lazy media: non-cover deck images use reveal's data-src, live
  iframes are lazified centrally by deck.js, and local raster images
  carry explicit width/height so layout and fit measurement are
  stable before load.
- Asset cleanup: six unused files removed (logo-bayreuth.webp,
  archive-backroom.jpg, kb-map-choropleth.png,
  logo-gemini-wordmark-2025.svg, notebooklm-qr-small.png,
  eisener-estate.svg); the seven files duplicated across decks (Ewé
  OCR scan + transcript, Brief/Extended demo shots, GLAM-E report,
  IWAC MCP server shot, MCP logo) moved to shared/assets/ with all
  references updated. _site/ and node_modules ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
- talks/_showcase: the full living layout catalogue (the former
  template), with a stable-vs-experimental component inventory in its
  header; never published (underscore folders stay out of the
  artifact).
- talks/_template: reduced to a minimal starter — cover, section
  divider, one content slide, closing — pointing authors at the
  showcase and the tooling.
- tools/new-talk.py: scaffold a talk in one command — safe dated slug,
  template copy, DECK_CONFIG/cover metadata fill (en/fr aware),
  manifest registration, landing-page regeneration, QR code to the
  canonical URL (qrcode package optional, graceful otherwise), refuses
  to overwrite, prints preview URL and next steps.
- audit: template/showcase placeholder assets exempt from the
  duplicate-file warning.

(4.1 shared components, 4.2 generic embeds and 4.4 the talk manifest
landed with Phases 1–2.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
- tools/export-pdf.mjs: notes-free slides.pdf per deck (reveal
  ?print-pdf, backgrounds on, page count verified against the slide
  count) plus a 1280×720 cover screenshot as each deck's social card;
  content-hash skip so unchanged decks reuse cached artifacts.
- tools/build-offline.py: one self-contained offline.zip per talk —
  deck at the root with shared/ references rewritten, assets, engine,
  fonts, the PDF, a serve.py launcher and local-server instructions.
- Per-deck metadata: meta description, canonical URL, Open Graph +
  Twitter card (og:image = the generated social card), locale, and
  schema.org PresentationDigitalDocument JSON-LD with presenters,
  event, language and date. new-talk.py injects the same block for
  future talks. (Landing-page search/filter landed with Phase 2.)
- LICENSE.md: MIT for the repository code, CC BY 4.0 for slide text
  and original figures, with vendored software, fonts, logos and
  externally sourced images explicitly carved out.
- THIRD_PARTY_NOTICES.md: full reveal.js MIT, highlight.js BSD and
  SIL OFL 1.1 texts (EB Garamond, Libre Franklin), plus the status of
  institutional logos and external images.
- .github/workflows/pages.yml: validation on pull requests and pushes
  — strip-notes tests, audit (repo + built site, strict),
  landing-page sync, Playwright browser checks at the three standard
  viewports; engine-change-gated visual regression on PRs with diff
  artifacts; build job produces the allowlisted notes-free site plus
  PDFs/social cards (cached by content hash) and offline bundles;
  deploy runs only from main after validation. Job timeouts set;
  first-party actions referenced by version tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
- sitemap.xml (generated by tools/build-index.py, sync-checked in CI),
  robots.txt and a branded 404 page, all added to the publication
  allowlist; audit resolves root-absolute references against the site
  root.
- Luxembourg SKILL.md embed carries data-source-url so its failure
  state links to the source repository; showcase QR labels use the
  canonical domain; landing-page extras row aligns with the number
  column on small screens.
- README rewritten for the new workflow: manifest-driven landing page,
  new-talk.py scaffolding, showcase/template split, slim highlighting,
  fit diagnostics (?check / ?no-fit / data-fit-allow), the validating
  deploy pipeline with PDFs and offline bundles, local validation
  commands, and licence pointers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
The visual job compared merge-base screenshots of talks/_template
against the head — but this PR intentionally rewrote the template
(catalogue → minimal starter), so the comparison measured the edit
itself and failed on ~95% pixel diffs. The check is only meaningful
when the shared engine changes while the photographed deck does not:

- screenshots now capture talks/_showcase (the actual catalogue),
  falling back to _template on older trees;
- the workflow runs the comparison only when shared/theme.css,
  deck.js or reveal/ changed AND the catalogue deck did not, emitting
  an explanatory notice otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122f4bMszLPwGVSkuLHt3er
@fmadore
fmadore merged commit 7c4b9ab into main Jul 10, 2026
4 checks passed
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