Files
awesome-copilot/website/README.md
T
David Pine d61dfdcddc fix(website): remediate WCAG accessibility issues and add axe regression guardrail (#2180)
* fix(website): remediate WCAG accessibility issues and add axe regression guardrail

Fixes accessibility violations found by an axe-core sweep of every website
page in both light and dark themes:

- aria-allowed-role (WCAG 1.3.1, 4.1.2): the shared resource card rendered
  an <article> with role="listitem", which is not an allowed role for that
  element. Switched the wrapper to a <div role="listitem"> so the listitem
  role is valid (affected every card, e.g. #arcade-canvas on /extensions/).
- aria-required-children (WCAG 1.3.1): removed role="list" from the tools,
  contributors, and cookbook containers whose children are not list items.
- nested-interactive (WCAG 4.1.2): removed tabIndex=0 from extension cards
  and rendered the author as a non-interactive span so no interactive
  control is nested inside another (the author link remains in the modal).
- color-contrast (WCAG 1.4.3): gave .btn-primary explicit white text with an
  AA-compliant hover (#7326d6), and bumped the dark-theme secondary text gray
  (--sl-color-gray-3) to #84849c (5.32:1) so ToC / meta / footer text passes.

Adds a checked-in regression guardrail:

- website/scripts/a11y-audit.mjs runs axe-core over all routes in both themes
  against the production build and fails on critical/serious violations only
  (moderate/minor are reported but non-blocking). Transitions/animations are
  disabled before sampling so axe measures settled, steady-state colors
  instead of mid-theme-transition frames.
- Adds npm scripts (website:a11y at the root, a11y in website/) and README
  docs. The matching Build Website CI step is proposed in the PR description
  (omitted from this commit because the authoring token lacks workflow scope).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(website): harden a11y audit per PR review

- Fail fast when a route navigation returns a non-2xx response, so the
  guardrail can't silently pass against a broken/missing route (page.goto
  resolves even for 4xx/5xx).
- Launch the Astro preview server via `node <astro-bin>` instead of
  `spawn(..., { shell: true })`. Removing the shell layer keeps signal
  delivery / detached-PGID shutdown predictable; resolving Astro's bin and
  running it with process.execPath also avoids the EINVAL that modern Node
  raises when spawning the npx.cmd shim without a shell on Windows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: David Pine <7679720+IEvangelist@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-07 11:11:17 +10:00

54 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Awesome GitHub Copilot website
Astro + Starlight site published to <https://awesome-copilot.github.com/>.
## Local development
Run these from the **repository root** (they generate the data the site needs first):
```bash
npm run website:data # generate public/data/*.json from repo content
npm run website:dev # generate data + start the dev server
npm run website:build # full production build
```
## Accessibility
The website has an automated axe-core + Playwright audit. Run it locally with `npm run website:a11y` from the repository root, or run `npm run a11y` from `website/` after building `dist` first.
CI blocks on critical and serious violations. Minor and moderate best-practice issues are reported as non-blocking.
Authoring conventions: resource cards use `div[role="listitem"]` wrappers, not `<article>`; only add `role="list"` to containers whose direct children are list items; do not nest interactive controls inside another focusable element; `.btn-primary` and ToC links must meet WCAG AA (4.5:1) contrast in both light and dark themes.
## Social preview cards (LinkedIn, etc.)
Shared links render as large preview cards driven by Open Graph / Twitter meta tags.
LinkedIn (and most platforms) read **Open Graph** — primarily `og:image` — while Twitter/X
also uses `twitter:card=summary_large_image`. Most tags are produced automatically:
- **Starlight defaults** emit `og:title`, `og:description`, `og:url`, `og:type`,
`og:site_name`, and `twitter:card=summary_large_image`.
- **`astro.config.mjs`** (global `head`) emits the shared image tags: `og:image`,
`og:image:width`, `og:image:height`, `og:image:alt`, and `twitter:image`.
- **`src/components/Head.astro`** adds `twitter:title`/`description`, `og:image:secure_url`,
`og:image:type`, and `twitter:image:alt`.
Each page's `title` and `description` (StarlightPage frontmatter) flow into the card text,
so keep them clear and benefit-focused.
### The image-dimension invariant
`og:image:width` / `og:image:height` in `astro.config.mjs` describe `public/images/social-image.png`
(currently **2400×1260**, ~1.91:1). Crawlers use these dimensions to understand the image and
may use them when selecting/rendering the preview. If you swap the image or add a per-page image
override, update the **full** image set so every tag stays consistent: `og:image`,
`og:image:width`, `og:image:height`, `og:image:alt`, and `twitter:image` (the last one matters
because `Head.astro` derives `og:image:secure_url` from `twitter:image` first).
### After deploying
LinkedIn caches scrapes aggressively. To force a refresh and confirm the card renders, run the
changed URL through the [LinkedIn Post Inspector](https://www.linkedin.com/post-inspector/).
HTML output alone doesn't prove the live card — verify the deployed image returns HTTP 200 over
HTTPS with `Content-Type: image/png` and no auth.