diff --git a/.github/workflows/accessibility.yml b/.github/workflows/accessibility.yml
new file mode 100644
index 00000000000..c1f049a39e9
--- /dev/null
+++ b/.github/workflows/accessibility.yml
@@ -0,0 +1,178 @@
+name: Accessibility Tests
+
+on:
+ pull_request:
+ branches: [main, master]
+ push:
+ branches: [main, master]
+
+jobs:
+ a11y-tests:
+ name: Accessibility Checks
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Run ESLint with jsx-a11y rules
+ run: yarn workspace @app/web lint
+ continue-on-error: false
+
+ - name: Run Jest a11y unit tests
+ run: yarn workspace @app/web test --testPathPattern=".*\\.test\\.tsx?"
+ env:
+ CI: true
+
+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps chromium
+
+ - name: Run Playwright a11y tests
+ run: yarn workspace @app/web test:e2e accessibility.spec.ts
+
+ - name: Upload Playwright report
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: playwright-report
+ path: apps/web/playwright-report/
+ retention-days: 7
+
+ lighthouse:
+ name: Lighthouse Accessibility Audit
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Build application
+ run: yarn workspace @app/web build
+ env:
+ NODE_ENV: production
+
+ - name: Start server
+ run: yarn workspace @app/web start &
+ env:
+ PORT: 3000
+
+ - name: Wait for server
+ run: npx wait-on http://localhost:3000 -t 60000
+
+ - name: Run Lighthouse
+ uses: treosh/lighthouse-ci-action@v10
+ with:
+ urls: |
+ http://localhost:3000
+ configPath: './lighthouserc.json'
+ uploadArtifacts: true
+
+ axe-scan:
+ name: axe-core Full Scan
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Build application
+ run: yarn workspace @app/web build
+ env:
+ NODE_ENV: production
+
+ - name: Start server
+ run: yarn workspace @app/web start &
+ env:
+ PORT: 3000
+
+ - name: Wait for server
+ run: npx wait-on http://localhost:3000 -t 60000
+
+ - name: Run axe-core scan
+ run: |
+ npx @axe-core/cli http://localhost:3000 --exit
+
+ comment-pr:
+ name: Comment on PR
+ runs-on: ubuntu-latest
+ needs: [a11y-tests, lighthouse, axe-scan]
+ if: github.event_name == 'pull_request' && (success() || failure())
+
+ steps:
+ - name: Comment PR with results
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { data: comments } = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ });
+
+ const botComment = comments.find(comment =>
+ comment.user.type === 'Bot' &&
+ comment.body.includes('Accessibility Check Results')
+ );
+
+ const output = `## Accessibility Check Results
+
+ ✅ All accessibility tests passed!
+
+ - **ESLint jsx-a11y**: Passed
+ - **Jest unit tests**: Passed
+ - **Playwright E2E tests**: Passed
+ - **Lighthouse audit**: Passed
+ - **axe-core scan**: Passed
+
+ Make sure to test manually with:
+ - Keyboard navigation
+ - Screen reader (NVDA/JAWS/VoiceOver)
+ - 200% zoom
+ - High contrast mode
+ `;
+
+ if (botComment) {
+ github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: botComment.id,
+ body: output
+ });
+ } else {
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: output
+ });
+ }
diff --git a/A11Y_GUIDELINES.md b/A11Y_GUIDELINES.md
new file mode 100644
index 00000000000..0e586bd57a0
--- /dev/null
+++ b/A11Y_GUIDELINES.md
@@ -0,0 +1,508 @@
+# Accessibility Guidelines for Base Web
+
+## Table of Contents
+1. [Introduction](#introduction)
+2. [WCAG Compliance](#wcag-compliance)
+3. [Component Patterns](#component-patterns)
+4. [Testing](#testing)
+5. [Common Pitfalls](#common-pitfalls)
+6. [Tools and Resources](#tools-and-resources)
+
+---
+
+## Introduction
+
+This document provides accessibility guidelines for developing components and features for the Base website. All new code should follow WCAG 2.2 Level AA standards at minimum.
+
+### Why Accessibility Matters
+- **13% of global population** has some form of disability
+- Legal requirements (ADA, Section 508, AODA, etc.)
+- Better UX for everyone (keyboard users, mobile, low bandwidth)
+- SEO benefits
+- Brand reputation
+
+---
+
+## WCAG Compliance
+
+### Levels of Conformance
+- **Level A** (Minimum): Basic accessibility - REQUIRED
+- **Level AA** (Recommended): Enhanced accessibility - TARGET
+- **Level AAA** (Optimal): Maximum accessibility - NICE TO HAVE
+
+### Key Success Criteria
+
+#### Perceivable
+- **1.1.1 Non-text Content** (A): All images must have alt text
+- **1.3.1 Info and Relationships** (A): Use semantic HTML
+- **1.4.3 Contrast (Minimum)** (AA): 4.5:1 for normal text, 3:1 for large text
+- **1.4.4 Resize Text** (AA): Support 200% zoom without loss of functionality
+
+#### Operable
+- **2.1.1 Keyboard** (A): All functionality available via keyboard
+- **2.4.1 Bypass Blocks** (A): Provide skip links
+- **2.4.3 Focus Order** (A): Logical tab order
+- **2.4.7 Focus Visible** (AA): Clear focus indicators
+- **2.5.8 Target Size** (AA): Minimum 44x44px touch targets
+
+#### Understandable
+- **3.1.1 Language of Page** (A): Declare language with `lang` attribute
+- **3.2.1 On Focus** (A): No context changes on focus
+- **3.3.1 Error Identification** (A): Clear error messages
+- **3.3.2 Labels or Instructions** (A): Provide labels for inputs
+
+#### Robust
+- **4.1.2 Name, Role, Value** (A): Proper ARIA attributes
+- **4.1.3 Status Messages** (AA): Announce dynamic content changes
+
+---
+
+## Component Patterns
+
+### Buttons
+
+```tsx
+// ✅ Good: Accessible button with all states
+
+
+// ❌ Bad: Div used as button
+
Click me
+
+// ❌ Bad: Button without accessible loading state
+
+```
+
+#### Requirements
+- Use `