Skip to content

fix(website): phase 2 & 3 visual audit — a11y, UX, SEO, perf, playground#413

Open
ajitpratap0 wants to merge 9 commits intomainfrom
fix/website-audit-phase2
Open

fix(website): phase 2 & 3 visual audit — a11y, UX, SEO, perf, playground#413
ajitpratap0 wants to merge 9 commits intomainfrom
fix/website-audit-phase2

Conversation

@ajitpratap0
Copy link
Owner

Summary

Comprehensive website audit covering accessibility (WCAG 2.2), Core Web Vitals, SEO, and UX polish across all 5 key pages (homepage, playground, benchmarks, VS Code, docs). All P0 and P1 issues resolved. Builds directly on the phase 1 audit merged in #406.


Accessibility (WCAG 2.2)

P0 — Blockers fixed

  • <main> landmark missing sitewide — root layout used <div id="main-content">, breaking skip links and screen reader navigation. Changed to <main> element.
  • Heading hierarchy — Footer nav group headings were <h2> after page <h3>s, creating non-sequential jumps. Demoted to <h3>.
  • Hydration mismatch on AnimatedCounter — server (en-IN locale) rendered 13,80,000 while client (en-US) rendered 1,380,000, crashing React hydration. Fixed by hardcoding 'en-US' locale.
  • Playground H1<h1 className="text-sm"> (14px visible heading) is semantically broken. Changed to <h1 className="sr-only"> + <span aria-hidden="true"> visible label.
  • Docs breadcrumb — bare <a> tags inside <nav> with no list structure. Wrapped in <ol>/<li>, added aria-label="Breadcrumb", aria-hidden separators.

P1 — Significant UX issues fixed

  • Navbar: aria-controls="mobile-menu" on hamburger + id="mobile-menu" on panel, aria-label="Main navigation" on <nav>, aria-current="page" on active links
  • FadeIn: useReducedMotion() from Framer Motion — zeroes y offset and duration when user prefers reduced motion
  • FeatureGrid: aria-hidden="true" on all 6 decorative SVGs (globe, lock, bolt, recycle, shield, cpu)
  • Button: exposed aria-label prop through to rendered element (external <a>, <Link>, <button>)
  • Playground dialect select: linked <label> to <select> via htmlFor/id; added aria-live="polite" on tab content panel
  • Playground copy buttons: all 4 output tabs (AST, Format, Lint, Analyze) now have copy-to-clipboard with 2s visual reset
  • SqlEditor: removed .cm-line { word-break: break-all } that was splitting SQL keywords mid-word

Performance / Core Web Vitals

Issue Fix
.container-width / .section-padding undefined Added CSS definitions — content was bleeding to viewport edges at 1440px
prefers-reduced-motion not respected Added global @media (prefers-reduced-motion: reduce) override in globals.css
AnimatedCounter hydration crash Hardcoded 'en-US' locale on all 3 .toLocaleString() calls
SqlEditor word-wrap Removed word-break: break-all — CodeMirror scroller handles overflow natively

SEO

Page Fix
Root layout Added robots: { index: true, follow: true } to base metadata
not-found.tsx Added noindex metadata for 404 page
blog/page.tsx Added alternates.canonical, openGraph block, refreshed description
benchmarks/page.tsx Added canonical + OpenGraph with absolute-form title
vscode/page.tsx Added canonical + OpenGraph
Navbar Renamed 'Blog''Changelog' to match actual page title
Docs breadcrumb Semantic <ol>/<li> structure aids crawling

Visual / UX

Component Fix
Hero.tsx Subtitle contrast rgba(255,255,255,0.5) (2.8:1 ❌) → text-zinc-300 (~5.9:1 ✓); responsive H1 scaling; removed redundant 3rd playground link
VersionBadge.tsx Badge text text-indigo-300 (~5.1:1 ✓) — was ~3.2:1 at 12px
BenchmarksContent.tsx Methodology→CTA gap pb-24pb-8; GoSQLX highlight row bg-indigo-500/5/10; removed duplicate Competitor Comparison section
VscodeContent.tsx Responsive H1 text-3xl sm:text-4xl md:text-5xl lg:text-6xl; mx-auto on content containers
SocialProof.tsx Section padding py-16py-8 (~200px gap removed)
mdx-components.tsx Right-edge fade gradient on code blocks for mobile scroll affordance
Hero.tsx Right-edge fade gradient on SQL <pre> at md:hidden

Playground

Tab Improvement
All tabs Copy-to-clipboard button in header bar with 2s "Copied!" feedback
FormatTab Added "read-only" badge alongside copy button
LintTab Copy serializes as [SEVERITY] rule message text format
AnalyzeTab grid-cols-3grid-cols-1 sm:grid-cols-3 (score cards overflowed at 390px)
Playground root aria-live="polite" on tab panel for screen reader announcements

Test plan

  • Run cd website && npm run build — zero TypeScript errors
  • Tab through homepage, playground, benchmarks, vscode pages keyboard-only — all elements reachable
  • Check document.querySelectorAll('main').length on any page — should return 1
  • Resize to 390px — AnalyzeTab score cards stack, no horizontal overflow
  • Toggle OS "Reduce Motion" — FadeIn animations should be instant (0ms)
  • Test playground copy buttons on all 4 tabs (AST, Format, Lint, Analyze)
  • Verify Navbar active link shows aria-current="page" attribute in DevTools

🤖 Generated with Claude Code

Ajit Pratap Singh and others added 9 commits March 17, 2026 21:43
…nt pages

P0 bugs:
- Guard onRouterTransitionStart behind NEXT_PUBLIC_SENTRY_DSN check to prevent
  spurious router.push() redirect loops when DSN is absent
- Remove clients.claim() from WASM service worker activate handler to prevent
  disruption of in-flight RSC fetches during page load
- Navbar: add pointerEvents:none to mobile menu initial/exit states to block
  iOS ghost click causing accidental navigation; add type="button" to hamburger
- Navbar: change all md: breakpoints → lg: so desktop nav collapses at 1024px

Homepage:
- AnimatedCounter: initialize display to real value to eliminate zero flash on mount;
  add prefers-reduced-motion guard to skip animation
- Hero: move overflow-hidden from section to blobs div; add break-words/hyphens-auto
  to headline; fix playground link contrast text-zinc-500 → text-zinc-300
- SocialProof: fix GitHub shields.io badge URL gosqlx/gosqlx → ajitpratap0/GoSQLX
- VscodeSection: fix publisher ID gosqlx.gosqlx → ajitpratap0.gosqlx

Playground:
- WasmLoader: fix callAndParse to separate JSON parse errors from error objects so
  Go WASM error responses propagate to callers instead of returning raw JSON strings
- AnalyzeTab: fix all field names to match actual Go JSON output (critical_count,
  high_count, medium_count, low_count from security; Score, QueryComplexity,
  Suggestions from optimization — PascalCase because no JSON struct tags in Go)
- Playground: fix breakpoints md: → lg: for side-by-side layout on desktop only

Content:
- GETTING_STARTED.md: replace all .md hrefs with /docs/ routes; update v1.6.0 → v1.12.0
- Sidebar: normalize trailing slash in isActive; add aria-current="page" to active link
  with visual left border accent
- Toc: add H2/H3 visual hierarchy (weight, size, indent, ellipsis + title tooltip)
- blog/page.tsx: rename "Release Notes" → "Changelog" in heading and metadata
- BenchmarksContent: add competitor comparison table (GoSQLX vs xwb1989, pg_query_go,
  blastrain/sqlparser)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds .github/workflows/glama-sync.yml which fires on every published
GitHub release and does two things in parallel:

1. bump-glama-version (continue-on-error):
   - Strips the `v` prefix from the release tag
   - Updates glama.json version field via jq
   - Commits "[skip ci]" back to the release branch
   - Best-effort: silently passes if branch protection rejects the push

2. trigger-glama-build:
   - POSTs to Glama's admin Dockerfile endpoint with:
       intent=build, pinnedCommitSha=<release SHA>
       full build config (Go 1.26.1 download + compile)
   - Pins the build to the exact release commit so Glama always
     runs the binary that matches the published release
   - Gracefully skips with setup instructions when
     GLAMA_SESSION_COOKIE secret is not configured
   - Fails with a clear message when the cookie has expired

Requires one-time manual setup:
  Repo Settings → Secrets → GLAMA_SESSION_COOKIE
  (Chrome DevTools → Network → copy Cookie header from glama.ai)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…builds)

The postbuild update-sw-hash script called fs.readFileSync on public/wasm/gosqlx.wasm
which is gitignored. Vercel's automatic preview builds don't run the WASM compile step
(only the GitHub Actions workflow does), causing every Vercel deployment to fail.

Add an fs.existsSync guard: when the binary is absent the script prints a warning and
exits 0 instead of throwing. The SW cache key remains unchanged in that case, which is
correct — Vercel preview builds don't serve the WASM anyway.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
go.mod requires go >= 1.26.1 but the Dockerfile was using golang:1.25-alpine
(Go 1.25.8), causing all Render builds to fail with:
  go: go.mod requires go >= 1.26.1 (running go 1.25.8; GOTOOLCHAIN=local)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Homepage:
- Fix invalid double <main> nesting (layout.tsx wraps in <div> now)
- StatsBar: grid layout prevents 3+1 orphan at tablet breakpoints
- StatsBar: unify performance stat to 1,380,000 (matches benchmarks page)
- Hero: improve hover contrast and mobile overflow handling
- McpSection: fix badge contrast (zinc-500→zinc-300), add MCP guide CTA

Playground:
- SqlEditor: CodeMirror fills container height via theme + h-full wrapper
- Playground: skeleton loading state mirrors real UI layout
- FormatTab: consistent overflow handling
- AnalyzeTab: C:0 H:0 M:0 L:0 severity format with hover tooltip

Benchmarks:
- Section heading, GoSQLX highlight row, CTA section
- Accessible aria-labels on ✓/✗ symbols
- Mobile swipe hint, improved dot contrast, last-updated label
- Updated page title with 1.38M ops/sec

Docs:
- TOC width: w-48 → w-56 (224px) for better readability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benchmarks page:
- Fix duplicate <main> landmark (use <div> wrapper)
- Standardize h2 headings to text-2xl font-bold
- Remove extra mt-16 from CTA section (fixes blank space gap)
- Add scope="col" to all <th> elements (WCAG 1.3.1)
- Add sr-only <caption> to both tables
- Fix version v1.12.1 → v1.12.0
- Add trailing slashes to CTA hrefs
- aria-hidden on methodology bullet dots
- Wrap -benchmem in <code> tag
- Add competitor measurement footnote
- Add page-specific openGraph + alternates.canonical

VS Code page:
- Fix duplicate <main> landmark (use <div> wrapper)
- Add sr-only <h2>Features</h2> (fix H1→H3 heading skip)
- aria-label on Install Extension CTA (new tab warning)
- aria-label on features <section>
- role/aria-label/tabIndex on <pre> Key Settings block
- Add page-specific openGraph + alternates.canonical

Shared components:
- FadeIn: respect prefers-reduced-motion via useReducedMotion()
- Navbar: aria-current="page" on active link + active text-white style
- Navbar: aria-label="Main navigation" on <nav>
- TerminalMockup: aria-hidden on decorative dots, break-all→break-words
- layout.tsx: relative canonical '/' (let pages override per-page)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keep branch improvements:
- Hero.tsx: mobile overflow fix (w-full max-w-full px-4 sm:px-0) and
  hover:text-white contrast improvement
- Navbar.tsx: aria-current="page" active nav link + usePathname

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…marks page

The second competitor comparison table (lines 186-238) was an exact
duplicate of the first, rendered back-to-back. It also lacked the
accessibility improvements (scope="col", aria-labels, sr-only caption)
that were present on the first. Remove the stale duplicate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…layground improvements

Accessibility (P0/P1):
- layout.tsx: wrap content in <main> landmark (was <div>); add robots metadata
- Navbar: aria-controls/id on hamburger+menu, aria-label on <nav>, aria-current="page" on active links
- Footer: demote nav group headings from h2→h3 (heading hierarchy fix)
- FadeIn: respect prefers-reduced-motion via useReducedMotion()
- FeatureGrid: aria-hidden="true" on all 6 decorative SVGs
- Button: expose aria-label prop through to rendered element
- docs breadcrumb: wrap in semantic <ol>/<li> with aria-label="Breadcrumb", aria-hidden separators

Performance / CWV:
- globals.css: define .container-width and .section-padding (were missing — content bled to edges)
- globals.css: add global prefers-reduced-motion override block
- AnimatedCounter: hardcode 'en-US' locale to fix server/client hydration mismatch
- SqlEditor: remove word-break:break-all (was splitting SQL keywords mid-word)

SEO:
- not-found.tsx: add 404 metadata with noindex
- blog/page.tsx: add canonical, openGraph block, refresh description
- benchmarks/page.tsx: add canonical, openGraph with absolute form title
- vscode/page.tsx: add canonical, openGraph
- constants.ts: rename nav label 'Blog'→'Changelog' to match page title
- docs/[...slug]: semantic breadcrumb structure

Visual / UX:
- Hero: fix subtitle contrast (rgba→text-zinc-300, ~5.9:1), responsive h1, remove redundant link
- VersionBadge: improve badge text contrast (text-indigo-300, ~5.1:1)
- BenchmarksContent: tighten methodology→CTA spacing (pb-24→pb-8), stronger GoSQLX row highlight
- VscodeContent: responsive h1 scaling, mx-auto on content containers
- SocialProof: reduce section padding py-16→py-8 (was ~200px gap)
- mdx-components: add right-edge fade gradient on code blocks for mobile scroll affordance

Playground:
- Playground: sr-only h1 with visible span, dialect select label association, aria-live on tab panel
- AstTab: add copy-to-clipboard button with 2s reset
- FormatTab: add copy button + read-only badge in header bar
- LintTab: add copy button (serializes as [SEVERITY] rule message text)
- AnalyzeTab: responsive score grid (grid-cols-1 sm:grid-cols-3, was overflowing at 390px)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gosqlx-website Ready Ready Preview, Comment Mar 18, 2026 10:58am

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.

1 participant