Skip to content

Make sponsors, people, projects and forms data-driven#94

Open
ramereth wants to merge 8 commits into
mainfrom
refresh/pr4-data-driven-content
Open

Make sponsors, people, projects and forms data-driven#94
ramereth wants to merge 8 commits into
mainfrom
refresh/pr4-data-driven-content

Conversation

@ramereth

Copy link
Copy Markdown
Member

PR 4 of the site refresh. Moves the last hand-maintained pages onto data files, so editing content means editing YAML instead of raw HTML. No visual redesign here — that landed in #92.

This also delivers two fixes that came out of the #92 review: staging form submissions no longer escape to production, and required checkbox groups actually block submission.

Forms

The five request forms were ~800 lines of copy-pasted Drupal-era HTML. They're now data/forms/*.yml plus a request-form shortcode; each page is down to its intro text and one line.

The formsender contract is unchanged. A parity script compares every control the browser will POST — field names, select option values, defaults, hidden envelope, action/method/enctype — between this branch and main, and they match. Two intentional exceptions:

  • the aarch64 distribution option value CentOS SteamCentOS Stream (typo)
  • the redirect value (below)

Also fixed along the way:

  • Staging escape: the formsender redirect pointed at production, so submitting a form on a staging deploy bounced you to the live site. request-form.js rebases it onto the current origin. No Jenkins change needed.
  • Checkbox groups: required can't express "at least one of these", so the OS Platform(s) groups on the two CI forms accepted empty submissions. Now enforced via the constraint-validation API, starting at the first submit attempt.
  • Accessibility, generated uniformly rather than per-form: programmatic labels, help text via aria-describedby, autocomplete on name/email, fieldset/legend groups.

Projects, people, sponsors

  • Eight project YAML files → data/projects/{hosted,aarch64,powerdev}.yml with status/category keys; one project_table shortcode replaces three. The hosted list's abused comma-separated description field becomes a real services array. Every table renders the same captions, counts and project sets as before; the homepage stat stays at 307.
  • data/people.yml + data/sponsors.yml drive the staff and sponsors pages. Heading anchors like #lance-albertson are preserved. Retires the line_break shortcode.
  • Tag1's link now points at tag1.com on both the homepage and the sponsors page — main had it pointing two different places. @ArtofBugs / @ramereth: worth a sanity check that this is the right domain.

Adversarial review

Everything above passed CI, so before opening this I ran a multi-agent adversarial review over the diff — independent finders per dimension, each finding then attacked by skeptics that had to refute it. 18 candidates, 15 refuted, 3 real. All three are fixed in 934802e, and two of them were mine, made while writing accessibility code:

  1. Phantom screen-reader error — my checkbox validation set the custom validity at page load, so Chrome exposed the first checkbox as invalid before you touched anything. A screen reader announced "Debian, checkbox, not checked, invalid entry" on a box nobody chose (WCAG 4.1.2). Someone could plausibly check Debian just to clear it and file a wrong ticket. pa11y reported 0 errors on this — no scanner catches it. Now enforced only after a submit attempt, with a visually-hidden "(required)" in the legend so the requirement is knowable up front.

  2. Search lost its deep links — putting the anchor id on <section> instead of <h2> made Pagefind record an anchor with empty text, which its sub-result filter discards. Searching "Tiffany" returned a bare "Staff" result instead of a link to #tiffany-chang. /about/people/ was the only page affected: 7 sub-results → 0. Now back to 7/7, verified by running the real indexer.

  3. My pa11y exemption was worse than the problem — in Madrone theme: Bootstrap 5.3, OSU design system, dark mode, WCAG AA #92 I added hideElements: ".form-select" to silence a contrast warning. But hideElements removes the element from the DOM both runners see, for all rules: I'd deleted 100% of select accessibility coverage from a gate documented as "no ignored rules". Proof — on a page where I broke a select's label association, the old config reports 0 errors, the new one catches 4.

    The right mechanism is levelCapWhenNeedsReview: "warning". axe's "needs review" means couldn't measure (an image behind the text), not found a failure. Capping those at warning keeps every rule running on every element while proven violations still fail the build. That let me drop the hero exemption too, so the config now matches its own claim. hideElements is left only for reCAPTCHA, which we genuinely can't fix.

Verification

  • Form POST parity vs main: identical
  • htmltest 222 documents; 50/50 alias stubs; markdownlint clean
  • pa11y-ci 15/15, now with less hidden from the scanners than before
  • 49/49 browser checks (redirect rebasing, checkbox groups, required selects, labels, error page)
  • All three fixes confirmed to survive --minify, which is what CI and production build with

Reviewer notes

  • Best read commit by commit; the data-file diffs are bulk moves.
  • The one thing worth real scrutiny is data/forms/*.yml — a wrong name: key silently breaks ticket routing, and the parity script only proves this branch matches main, not that main was right.

🤖 Generated with Claude Code

ramereth and others added 6 commits July 13, 2026 17:13
- The hook's trailing newline rendered as a visible space between a
  link and any punctuation directly after it ("(CGRB) , our")
- Trim it with a {{- "" -}} guard; verified zero link-then-punctuation
  gaps remain across the built site

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
- Move each form's fields into data/forms/<name>.yml; pages shrink to
  intro text plus a request-form shortcode
- New form-field partial renders Bootstrap form markup with programmatic
  labels, aria-describedby help text, autocomplete on name/email, and
  fieldset/legend checkbox groups
- Share formsender settings in [params.formsender]; POST field names and
  values verified identical to the old forms
- Rebase the formsender redirect onto the current origin via
  request-form.js so staging/local submissions no longer land on
  production
- Enforce "at least one" on required checkbox groups through the
  constraint-validation API
- Fix the aarch64 "CentOS Steam" option value and the empty required
  spans on the IBM Z form; drop the legacy webform compat CSS
- Exempt .form-select from the axe scan (chevron background-image makes
  contrast unverifiable); real contrast checked in both modes during QA
- Document the forms data model in the README

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
- data/projects/{hosted,aarch64,powerdev}.yml replace the per-table
  YAML files; entries carry status (current/former) and, for powerdev,
  category (foss/academic/gpu)
- The hosted list's comma-separated description strings become proper
  services arrays
- One project_table shortcode (data/status/category/title params)
  replaces project_table, hosted_projects_table, and former_projects;
  rows now sort by name
- Verified every table renders the same captions, counts, and project
  sets as before; homepage stat stays at 307

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
- New people shortcode renders each entry (portrait, bio, contact rows)
  and keeps the existing heading anchors like #lance-albertson
- Lance's email moves from a bio sentence to a labeled contact row;
  fix "soruce" and "sophmore" typos in bios
- Retire the line_break shortcode (the section styles replace it)
- Add /about/people/ to the pa11y scan set (14/14 URLs pass)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
- Add per-sponsor blurbs to the data file the homepage strip already
  uses; the page becomes intro text plus a sponsors shortcode
- Logos render through the responsive-image partial instead of the
  #sponsors fragment hack
- Point Tag1 at tag1.com (their current domain) on both the homepage
  strip and the sponsors page
- Add /about/sponsors/ to the pa11y scan set (15/15 URLs pass)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
An adversarial review of this branch compared the rendered output against
main and turned up three real regressions that the existing test suites
missed: an accessibility bug in the new form validation, a silent loss of
search functionality, and a hole in the accessibility gate itself. None
affect the formsender POST contract. Fixes below, each verified in a
browser.

- Enforce checkbox groups on submit, not at load, so screen readers
  don't hear a phantom error; legend now says "(required)"
- Move the people anchor id to the h2 so Pagefind restores the 7
  per-person search sub-results
- Cap axe "needs review" at warning instead of hiding the hero and
  selects, which had deleted all scanner coverage of them

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
@ramereth
ramereth requested a review from ArtofBugs July 14, 2026 20:15
Comment thread data/forms/aarch64-hosting.yml Outdated
Comment thread .pa11yci.js Outdated
Comment thread layouts/_shortcodes/people.html Outdated
Three changes from ArtofBugs' review: make the OpenStack Access dropdown
a required choice, stop hand-maintaining the accessibility scan's URL
list, and show full URLs as link text on the staff page. Generating the
URL list immediately caught a WCAG failure on a never-scanned page:
Hugo's default monokai syntax highlighting is 3.93:1 on
/services/powerdev/opence/.

- OpenStack Access is now required with a "- Select -" placeholder,
  matching flavor/distribution, so tickets always carry a real choice
  (Lance's call on the review thread)
- .pa11yci.js walks the built site instead of listing URLs by hand:
  every unique page is scanned (41 URLs, 26 never scanned before), with
  blog posts and tag pages sampled by one representative each and alias
  stubs skipped. PA11Y_FULL=1 sweeps all 172 pages for launch prep and
  content audits (documented in the README; passes today in ~4 minutes)
- Switch syntax highlighting to modus-vivendi, designed for WCAG
  conformance; worst token contrast is now 8.83:1 (was 3.93:1)
- Staff GitHub links display the full URL as their text

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
@ramereth
ramereth requested a review from ArtofBugs July 15, 2026 18:04
Comment thread .pa11yci.js
ArtofBugs
ArtofBugs previously approved these changes Jul 17, 2026
Review question on PR 94: the sort is for a deterministic, greppable
scan log — the walk emits directory-traversal order and POSIX leaves
readdir ordering unspecified. Measured cost is ~0.03ms against a scan
that takes minutes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lance Albertson <lance@osuosl.org>
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