Skip to content

Commit e3fa6f0

Browse files
ajitpratap0Ajit Pratap Singhclaude
authored
fix(website): complete site audit — animation, a11y, SEO, security, perf, content fixes (#396#405) (#406)
* audit(website): SEO findings for gosqlx.dev Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * audit(website): security findings for gosqlx.dev Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * audit(website): functional findings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * audit(website): content findings for 2026-03-17 Adds content audit covering version currency, blog post coverage gaps, docs completeness, link health, unused large SVG assets, and redirect configuration for gosqlx.dev. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * audit(website): accessibility findings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * audit(website): visual/responsive findings for 2026-03-17 Captures screenshots at 320, 390, 768, 1280, 1440px across homepage, playground, docs, blog, and benchmarks pages. Documents critical issues including homepage sections invisible below hero (scroll-animation bug), widespread horizontal overflow at 320–390px, benchmarks table hidden on mobile, and stats counters stuck at zero. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: allow Sentry BSL and Rollup 0BSD licenses in dependency review * fix(website): audit quick-wins — canonical, JSON-LD, security headers, skip-nav, broken links, unused assets - Fix robots.txt sitemap URL (sitemap-index.xml → sitemap.xml) so Googlebot can discover sitemap - Delete 1.28 MB of unused logo assets (logo-text.svg 931KB, logo.svg 309KB, logo.png 44KB) - Fix GitHub owner links site-wide: ajitpsingh → ajitpratap0 in Footer.tsx and Navbar.tsx - Add HSTS (max-age=31536000; includeSubDomains; preload) and Permissions-Policy headers - Remove unsafe-eval from CSP script-src; add frame-ancestors/base-uri/form-action directives - Add alternates.canonical to layout (homepage), docs pages, and blog pages - Add JSON-LD SoftwareApplication structured data in root layout - Fix og:url on docs and blog pages to use per-page URLs - Add skip-to-main-content link (WCAG 2.4.1) and wrap page content in <main id="main-content"> - Remove broken Vercel Analytics component (was causing 2x 404 console errors per page) - Add audit SUMMARY.md with all findings and GitHub issue references (#396#405) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): make not-found.tsx a server component for proper 404 HTTP status (issue #397) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): always-visible animations and mobile overflow (issues #396, #401) - FadeIn: replace whileInView with animate so sections are always visible after mount, regardless of IntersectionObserver timing or SSR context - AnimatedCounter: remove useInView dependency; start spring animation via setTimeout after mount so counters always count up - globals.css: add overflow-x: hidden to html and body to prevent horizontal scroll at any viewport width - Hero: responsive heading (text-3xl sm:text-5xl md:text-6xl lg:text-7xl), flex-wrap on button row, stacked divider fix for code preview grid on mobile - TerminalMockup: add overflow-x-auto and break-all so long command strings don't overflow at 320px Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): color contrast WCAG AA and keyboard-accessible code blocks (issues #399, #400) - Navbar: text-zinc-400 → text-zinc-300 for all nav links and GitHub icon (desktop + mobile) - Footer: text-zinc-500 → text-zinc-400 for description and links; text-zinc-600 → text-zinc-400 for copyright - Sidebar: text-zinc-500 → text-zinc-400 for category heading buttons - mdx-components: add tabIndex={0} and focus:ring-2 to <pre> for keyboard-scrollable code blocks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): WCAG AA color contrast — nav links, footer, sidebar (issue #399) - Navbar: text-zinc-400 → text-zinc-300 for all nav links and GitHub icon (desktop + mobile), ~8.7:1 contrast - Footer: text-zinc-500 → text-zinc-400 for description and links; text-zinc-600 → text-zinc-400 for copyright - Sidebar: text-zinc-500 → text-zinc-400 for category heading buttons Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): fix broken .md links in docs and add missing blog post (issues #398, #405) - Fix relative docs/MIGRATION.md link in CHANGELOG.md (v1.9.2 section) to use absolute GitHub URL, resolving 404 in rendered blog post - Fix CHANGELOG.md v1.12.1 header using hyphen separator instead of em-dash, causing split-changelog.js to skip the entry (regex expects em-dash) - Regenerate all 15 blog posts; v1-12-1.md now generated correctly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(website): add WASM preload hint and versioned SW cache key (issues #402, #403) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * seo(website): add JSON-LD Article to blog posts and BreadcrumbList to docs pages (issue #404) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): skip SW hash update when WASM binary absent in CI postbuild crashes with ENOENT when gosqlx.wasm is not present (Lighthouse CI, dependency review, etc.). Guard with existsSync so the build succeeds in environments that don't ship the binary. * fix(ci): build WASM before website build in Lighthouse CI The postbuild script hashes public/wasm/gosqlx.wasm to stamp a content-addressed cache key into the service worker. Lighthouse CI was missing the Go + WASM build steps that website.yml already has, so the binary was absent and the build crashed with ENOENT. Added: Setup Go 1.26 → make build in wasm/ → copy binary to public/wasm/ Reverted the existsSync guard hack added in the previous commit. Bumped timeout to 15m to accommodate the Go build. * fix(website): fix playground accessibility for Lighthouse ≥0.95 (WCAG tabpanel, labels, ARIA) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(website): simplify SqlEditor aria-label — remove redundant fallbacks * fix(website): fix WCAG AA contrast in playground — slate-500/600 → slate-400 All text-slate-500, text-slate-600, and text-zinc-500 classes in playground components render ~4.19:1 contrast on the #09090b background, failing WCAG AA (requires 4.5:1 for small text). Bumped to slate-400/zinc-400 which gives ~8:1. Also removed aria-controls from inactive tab buttons — they were pointing to tabpanel IDs that don't exist in the DOM (only the active panel is rendered), which violates aria-valid-attr-value. Files: Playground.tsx, AstTab.tsx, LintTab.tsx, AnalyzeTab.tsx, FormatTab.tsx, WasmErrorBoundary.tsx * fix(a11y): fix 4 Lighthouse accessibility failures blocking CI Based on Lighthouse report artifact analysis, 4 weighted audits were failing on /playground: 1. aria-input-field-name (weight=7): CodeMirror's cm-content[role=textbox] had no accessible name. Fixed with EditorView.contentAttributes.of() to pass aria-label directly to the cm-content element. 2. color-contrast (weight=7): oneDark theme's coral (#e06c75) on #282c34 background yields 4.38:1 ratio (fails WCAG AA 4.5:1). Override with custom HighlightStyle (#e87980 → ~5.07:1 contrast) placed before oneDark for higher CM6 precedence. 3. heading-order (weight=3): Footer h3 elements skipped h2 after h1 in Playground, failing sequential heading order. Changed footer section labels from h3 to h2. 4. image-redundant-alt (weight=1): Logo images had alt="GoSQLX" while parent links also contained "GoSQLX" text (redundant). Changed to alt="" (decorative) in Navbar and Footer. Also adds @lezer/highlight as direct dependency (was transitive). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini-2655.local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 353cae1 commit e3fa6f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1381
-133
lines changed

.github/workflows/lighthouse.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,22 @@ on:
1313
jobs:
1414
lighthouse:
1515
runs-on: ubuntu-latest
16-
timeout-minutes: 10
16+
timeout-minutes: 15
1717
steps:
1818
- uses: actions/checkout@v4
1919

20+
- name: Setup Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: '1.26'
24+
25+
- name: Build WASM
26+
run: |
27+
cd wasm && make build
28+
mkdir -p ../website/public/wasm
29+
cp playground/gosqlx.wasm ../website/public/wasm/
30+
cp playground/wasm_exec.js ../website/public/wasm/
31+
2032
- name: Setup Node
2133
uses: actions/setup-node@v4
2234
with:

.github/workflows/security.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,11 @@ jobs:
168168
# to handle golang.org/x packages which report as compound license
169169
allow-licenses: >-
170170
MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC,
171-
BlueOak-1.0.0, OFL-1.1, CC-BY-4.0, MPL-2.0,
171+
BlueOak-1.0.0, OFL-1.1, CC-BY-4.0, MPL-2.0, 0BSD,
172172
LicenseRef-scancode-google-patent-license-golang,
173-
BSD-3-Clause AND LicenseRef-scancode-google-patent-license-golang
173+
BSD-3-Clause AND LicenseRef-scancode-google-patent-license-golang,
174+
LicenseRef-bad-fsl-1.1-mit,
175+
0BSD AND ISC AND MIT
174176
175177
govulncheck:
176178
name: Go Vulnerability Check

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All notable changes to GoSQLX will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [1.12.1] - 2026-03-15 - Website Performance & Mobile Optimization
8+
## [1.12.1] - 2026-03-15 Website Performance & Mobile Optimization
99

1010
### Improved
1111
- Lighthouse Desktop: 100 Performance, 100 Accessibility, 100 SEO
@@ -508,7 +508,7 @@ if tok.Type == models.TokenTypeSelect { ... }
508508

509509
**Who is affected:** Only users who directly access `token.Token` fields or use string-based token constants from `pkg/sql/token`. Users of the high-level `gosqlx.Parse()` / `gosqlx.Validate()` API are **not affected**.
510510

511-
See [docs/MIGRATION.md](docs/MIGRATION.md) for detailed migration instructions.
511+
See [Migration Guide](https://github.com/ajitpratap0/GoSQLX/blob/main/docs/MIGRATION.md) for detailed migration instructions.
512512

513513
---
514514

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# GoSQLX Website Audit Summary — 2026-03-17
2+
3+
## Overall Health
4+
5+
| Category | Top Finding | Status |
6+
|----------|-------------|--------|
7+
| Performance | JS 627KB home / 985KB playground; WASM no preload | 🟡 |
8+
| SEO | No canonical tags; broken sitemap discovery; no JSON-LD | 🔴 |
9+
| Accessibility | No skip link; contrast failures; code blocks not keyboard accessible | 🟡 |
10+
| Security | Missing HSTS + Permissions-Policy; unsafe-eval in CSP | 🟡 |
11+
| Visual/Responsive | Homepage sections invisible below hero; overflow at 320px | 🔴 |
12+
| Functional | Wrong GitHub owner links; 404 returns 200; broken .md doc links | 🔴 |
13+
| Content | 1.28 MB unused assets; missing blog post for latest release | 🟡 |
14+
15+
## Fixes Applied in This PR
16+
17+
| # | Fix | File Changed | Impact |
18+
|---|-----|--------------|--------|
19+
| 1 | Fixed robots.txt sitemap URL | website/public/robots.txt | SEO: sitemap now discoverable |
20+
| 2 | Deleted 1.28 MB unused assets | website/public/images/ | Perf: reduced repo size |
21+
| 3 | Fixed GitHub owner links (ajitpsingh → ajitpratap0) | website/src/components/layout/Footer.tsx, Navbar.tsx | Functional: correct repo links site-wide |
22+
| 4 | Added HSTS + Permissions-Policy security headers | website/next.config.ts | Security |
23+
| 5 | Removed unsafe-eval from CSP; added frame-ancestors/base-uri/form-action | website/next.config.ts | Security |
24+
| 6 | Added canonical to layout (homepage) | website/src/app/layout.tsx | SEO |
25+
| 7 | Added JSON-LD SoftwareApplication structured data | website/src/app/layout.tsx | SEO |
26+
| 8 | Added canonical + og:url to docs pages | website/src/app/docs/[...slug]/page.tsx | SEO |
27+
| 9 | Added canonical + og:url + og:type to blog pages | website/src/app/blog/[slug]/page.tsx | SEO |
28+
| 10 | Added skip-to-main-content link | website/src/app/layout.tsx | A11y |
29+
| 11 | Wrapped page content in `<main id="main-content">` | website/src/app/layout.tsx | A11y |
30+
| 12 | Removed broken Vercel Analytics component | website/src/app/layout.tsx | Perf: eliminates 2 console errors per page |
31+
32+
## GitHub Issues Created for Complex Fixes
33+
34+
- #396 — fix(website): homepage sections invisible below hero (IntersectionObserver)
35+
- #397 — fix(website): 404 page returns HTTP 200 status
36+
- #398 — fix(website): broken .md links in docs content files
37+
- #399 — a11y(website): fix color contrast violations
38+
- #400 — a11y(website): make code blocks keyboard accessible (tabindex=0)
39+
- #401 — fix(website): horizontal overflow at 320px viewport
40+
- #402 — perf(website): add rel=preload for gosqlx.wasm
41+
- #403 — perf(website): version WASM service worker cache key
42+
- #404 — seo(website): add JSON-LD Article to blog, BreadcrumbList to docs
43+
- #405 — content(website): add blog post for latest release
44+
45+
## Audit Reports
46+
- [Performance](performance.md)
47+
- [SEO](seo.md)
48+
- [Accessibility](accessibility.md)
49+
- [Security](security.md)
50+
- [Functional](functional.md)
51+
- [Content](content.md)
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Accessibility Audit — 2026-03-17
2+
3+
**Tool**: axe-core 4.10.0 (WCAG 2A, 2AA, 2.1AA, best-practice ruleset)
4+
**Pages audited**: https://gosqlx.dev (homepage), https://gosqlx.dev/docs/getting-started
5+
**Auditor**: Claude Code automated audit
6+
7+
---
8+
9+
## axe-core Violations Summary
10+
11+
| Page | Critical | Serious | Moderate | Minor | Passes | Incomplete |
12+
|------|----------|---------|----------|-------|--------|------------|
13+
| Homepage (`/`) | 0 | 1 | 0 | 1 | 38 | 1 |
14+
| `/docs/getting-started` | 0 | 2 | 1 | 1 | 40 | 0 |
15+
16+
**Total unique violations across both pages: 4 distinct rules triggered**
17+
18+
---
19+
20+
## Detailed Violations
21+
22+
### Homepage Violations
23+
24+
#### serious: scrollable-region-focusable
25+
- **Description**: Ensure elements that have scrollable content are accessible by keyboard
26+
- **WCAG Criterion**: WCAG 2.1 SC 2.1.1 (Keyboard, Level A)
27+
- **Nodes affected**: 1
28+
- **Example HTML**: `<pre class="p-4 text-[13px] leading-relaxed font-mono text-zinc-400 overflow-x-auto max-h-[320px]">`
29+
- **Fix**: Add `tabindex="0"` to each `<pre>` block that has `overflow-x-auto` or `overflow-y-auto` so keyboard users can scroll into the region. For the hero code block and AST output panel specifically.
30+
31+
#### minor: image-redundant-alt
32+
- **Description**: Ensure image alternative text is not repeated as adjacent visible text
33+
- **WCAG Criterion**: Best practice (not a hard WCAG fail, but degrades screen-reader UX)
34+
- **Nodes affected**: 2 (both logo images — header and footer)
35+
- **Example HTML**: `<img alt="GoSQLX" ...>` inside `<a>` that also contains `<span>GoSQLX</span>`
36+
- **Fix**: Set `alt=""` on the logo `<img>` when the adjacent `<span>GoSQLX</span>` text is already present, making the image purely decorative. The link itself is adequately labelled by the text node.
37+
38+
---
39+
40+
### /docs/getting-started Violations
41+
42+
#### serious: color-contrast
43+
- **Description**: Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds (4.5:1 for normal text, 3:1 for large text)
44+
- **WCAG Criterion**: WCAG 2.1 SC 1.4.3 (Contrast Minimum, Level AA)
45+
- **Nodes affected**: 19
46+
- **Example HTML**:
47+
- `<a class="hover:text-white transition-colors" href="/docs">Docs</a>` — nav links at ~65% lightness on dark background
48+
- `<span>Getting Started</span>` — breadcrumb text
49+
- **Fix**: Nav link color `lab(65.6464 ...)` (~`#9ca3af` / zinc-400) on the dark `#18181b` background gives approximately 3.5:1 — below 4.5:1 required for 14px normal text. Increase to `text-zinc-300` (`#d4d4d8`) or lighter to achieve ≥4.5:1. Breadcrumb spans and sidebar section labels have the same issue.
50+
51+
#### serious: scrollable-region-focusable
52+
- **Description**: Same as homepage — `<pre>` code blocks with overflow are not keyboard-reachable
53+
- **WCAG Criterion**: WCAG 2.1 SC 2.1.1 (Keyboard, Level A)
54+
- **Nodes affected**: 13 (all code blocks on the getting-started page)
55+
- **Example HTML**:
56+
- `<pre><code class="language-bash">go install ...</code></pre>`
57+
- `<pre>` (inline code blocks throughout)
58+
- **Fix**: Same as homepage — add `tabindex="0"` to all `<pre>` elements that may overflow. Consider a shared `CodeBlock` component that applies this automatically.
59+
60+
#### moderate: landmark-unique
61+
- **Description**: Ensure landmarks are unique — two `<nav>` elements on the page share the same role with no distinguishing accessible name
62+
- **WCAG Criterion**: WCAG 2.1 SC 1.3.6 (Identify Purpose, Level AAA) / Best practice
63+
- **Nodes affected**: 1
64+
- **Example HTML**: `<nav class="mx-auto max-w-7xl flex items-center ...">`
65+
- **Fix**: Add `aria-label` to each `<nav>` to distinguish them. E.g., `aria-label="Primary"` on the top navbar, `aria-label="Docs sidebar"` on the docs sidebar nav, `aria-label="Breadcrumb"` on breadcrumb navigations.
66+
67+
#### minor: image-redundant-alt
68+
- **Description**: Same as homepage — logo image alt duplicates adjacent text
69+
- **WCAG Criterion**: Best practice
70+
- **Nodes affected**: 2 (header and footer logo)
71+
- **Fix**: Same as homepage — set `alt=""` on the logo `<img>`.
72+
73+
---
74+
75+
## Structural Checks
76+
77+
### Heading Hierarchy — Homepage
78+
79+
```
80+
H1: Parse SQL at the speed of Go
81+
H2: Built for Production
82+
H3: Multi-Dialect
83+
H3: Thread-Safe
84+
H3: Zero-Copy
85+
H3: Object Pooling
86+
H3: Security Scanner
87+
H3: MCP Server
88+
H2: Simple, Powerful API
89+
H2: AI-Ready SQL Tools
90+
H2: IDE Integration
91+
H2: Ready to parse SQL at the speed of Go?
92+
H3: Product (footer)
93+
H3: Resources (footer)
94+
H3: Community (footer)
95+
```
96+
97+
**Assessment**: Hierarchy is well-formed. Single H1, logical H2 sections, H3 subsections. No heading levels are skipped. Footer H3s are semantically reasonable as section labels. No issues found.
98+
99+
---
100+
101+
### Skip Link
102+
103+
- **Status**: MISSING — no skip-to-main-content link found on homepage or docs page
104+
- **WCAG Criterion**: WCAG 2.1 SC 2.4.1 (Bypass Blocks, Level A)
105+
- **Impact**: Keyboard-only users must tab through the entire navigation bar on every page load before reaching main content.
106+
- **Fix**: Add a visually-hidden skip link as the very first focusable element in `<body>`, revealed on focus:
107+
108+
```jsx
109+
// In your root layout (e.g., app/layout.tsx), before <Header />:
110+
<a
111+
href="#main-content"
112+
className="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-indigo-600 focus:text-white focus:rounded"
113+
>
114+
Skip to main content
115+
</a>
116+
```
117+
118+
Then add `id="main-content"` to the `<main>` element.
119+
120+
---
121+
122+
### Image Alt Text — Homepage
123+
124+
| Image | Alt Text | Status |
125+
|-------|----------|--------|
126+
| Logo (header) | "GoSQLX" | Redundant — adjacent span also says "GoSQLX"; use `alt=""` |
127+
| GitHub Stars badge | "GitHub Stars" | OK |
128+
| Tests badge | "Tests" | OK |
129+
| Go Report Card badge | "Go Report Card" | OK |
130+
| GoDoc badge | "GoDoc" | OK |
131+
| Logo (footer) | "GoSQLX" | Redundant — same issue as header logo; use `alt=""` |
132+
133+
**Overall**: All images have `alt` attributes present. The only issue is the two logo instances where the alt duplicates visible text (see violation above). Feature-section icons appear to be SVG/CSS, not `<img>` tags — not audited here but should be checked if they convey meaning.
134+
135+
---
136+
137+
### Focus Indicators
138+
139+
- **Focus CSS rules found via stylesheet inspection**: None detected from accessible stylesheets (external Next.js chunks are cross-origin and unreadable by `cssRules`)
140+
- **Tailwind default**: Tailwind v3 removes the browser default `outline` on focus for many elements (`outline: 2px solid transparent`). The site uses `focus-visible:ring-*` utilities in Tailwind, which are applied via class strings in components.
141+
- **Observed in snapshot**: Interactive elements (buttons, links, nav items) do not expose explicit focus-ring class names in the axe output.
142+
- **Recommendation**: Audit interactively by tabbing through the page. Confirm `focus-visible:ring-2 focus-visible:ring-indigo-500` (or equivalent) is applied to all interactive elements: nav links, CTA buttons ("Get Started", "Try Playground"), tab switcher buttons ("Parse", "Format", "Validate", "Lint"), and footer links.
143+
- **Known gap**: The API tab buttons (`<button "Parse">`, `<button "Format">` etc.) in the homepage code demo should be verified to have visible focus rings.
144+
145+
---
146+
147+
## Color Contrast Analysis
148+
149+
Based on computed styles captured from the live page:
150+
151+
| Element | Color (approx hex) | Background | Estimated Ratio | WCAG AA Pass? |
152+
|---------|-------------------|------------|-----------------|---------------|
153+
| Nav links (Docs, Playground, Blog…) | ~`#a1a1aa` (zinc-400) | `#18181b` (zinc-950) | ~3.5:1 | FAIL (need 4.5:1 for 14px) |
154+
| "Get Started" button text | ~`#000000` | `#ffffff` | 21:1 | PASS |
155+
| Code panel labels (query.sql, AST Output) | ~`#71717a` (zinc-500) | dark panel bg | ~3.0:1 | FAIL (need 4.5:1 for 12px) |
156+
| Footer links | ~`#a1a1aa` (zinc-400) | `#18181b` | ~3.5:1 | FAIL (need 4.5:1 for 14px) |
157+
| Logo text "GoSQLX" (nav) | ~`#fafafa` (zinc-50) | `#18181b` | ~17:1 | PASS |
158+
159+
> Note: Ratios estimated using the WCAG relative luminance formula on the captured RGB values. Exact values depend on actual rendered background. The dark-themed site uses zinc-400/zinc-500 text on zinc-950 backgrounds throughout — this color pairing recurs at least 19 times (per axe node count on docs page).
160+
161+
---
162+
163+
## Priority Fixes (WCAG 2.1 AA Compliance)
164+
165+
Ranked by severity and user impact:
166+
167+
1. **Add skip-to-main-content link** — WCAG 2.4.1 (Level A) — Effort: **Low**
168+
- Affects all keyboard and screen-reader users on every page. Single change in root layout. No visual impact for mouse users.
169+
170+
2. **Fix color contrast for nav links, breadcrumbs, code labels** — WCAG 1.4.3 (Level AA) — Effort: **Low/Med**
171+
- 19+ affected nodes on docs pages. Change `text-zinc-400``text-zinc-300` (or lighter) for all body/nav link text on dark backgrounds. Update the Tailwind color tokens used for secondary text in the dark theme. This fixes the most-cited violation by axe.
172+
173+
3. **Add `tabindex="0"` to all scrollable `<pre>` code blocks** — WCAG 2.1.1 (Level A) — Effort: **Low**
174+
- Affects 1 element on homepage, 13 on docs page (all code examples). Create a shared `CodeBlock` component (or update the existing one) to always include `tabindex="0"` when `overflow-*` is applied. Keyboard users currently cannot scroll horizontally into long code examples.
175+
176+
4. **Add `aria-label` to distinguish multiple `<nav>` landmarks** — Best practice / WCAG 1.3.6 — Effort: **Low**
177+
- Affects docs pages with sidebar. Adds `aria-label="Primary"` to header nav, `aria-label="Documentation sidebar"` to sidebar nav. One-line fix per nav element.
178+
179+
5. **Fix redundant logo alt text** — Best practice — Effort: **Low**
180+
- Change `alt="GoSQLX"` to `alt=""` on logo `<img>` in header and footer links where the adjacent `<span>GoSQLX</span>` text provides the accessible name.
181+
182+
---
183+
184+
## Additional Observations
185+
186+
- **Console errors**: Two errors on every page load — `_vercel/insights/script.js` 404 and a CSP block on an external analytics script. These do not affect accessibility but indicate a broken analytics integration.
187+
- **Stats section counter animation**: The animated counters ("0+" ops/sec, "0μs" latency) start at 0 before animating to real values. Screen readers will announce "0" initially. Consider using `aria-live="polite"` with a debounced update, or providing static values with a `<noscript>` fallback.
188+
- **Interactive code demo (homepage)**: The tab buttons ("Parse", "Format", "Validate", "Lint") lack visible labels for two of the four buttons in the axe snapshot (`button "Format"`, `button "Validate"`, `button "Lint"` have no text in some states). Confirm these have accessible names in all states.
189+
- **"Open Full Playground" link**: Contains an `<img>` with no captured alt in the axe snapshot — verify this is `alt=""` with `aria-hidden="true"` since the link text already conveys the purpose.

0 commit comments

Comments
 (0)