A newer version of the Gradio SDK is available: 6.20.0
Architecture β Color-UX-Access
How the system works: screenshot β CVD simulation β VLM β WCAG report. For deployment specifics, see
docs/DEPLOYMENT.md. For test patterns, seedocs/TESTING.md.
Overview
Purpose: Simulate how any webpage screenshot looks through the eyes of a colorblind user, then use a 32B VLM to audit it as an accessibility expert would β reporting findings against WCAG 2.1 standards.
Serves: A person with CVD (8% of men, 0.5% of women) who encounters sites daily using color alone to convey meaning β error states, required fields, status indicators.
Philosophy: The app is a proxy for the user's own eyes. It captures the visual experience the way a colorblind user would encounter it β not how the DOM is structured.
System Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER FLOW β
β Upload PNG βββΊ CVD Gallery (10 types) βββΊ WCAG Report β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Screenshot (file upload)
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Stage 1: CVD Simulation (CPU β instant, no GPU needed) β
β 10 variants via deficiency_config (8 DaltonLens + 2 grayscale) β
β β Gallery: original + protanopia, deuteranopia, tritanopia, β
β protanomaly, deuteranomaly, tritanomaly, β
β severe_protanopia, severe_deuteranopia, β
β achromatopsia, achromatomaly β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Stage 2: VLM Inference (GPU β ~90s first call, <5s cached) β
β β
β Local dev: analyze_with_vlm() β HF Router API β
β β CohereLabs/aya-vision-32b β
β β
β HF Space: @spaces.GPU(duration=120) wraps entire UI β
β same HF Router API β same model β
β β
β Modal: upload_screenshot() β vlm_inference_fn(A10G) β
β same HF Router API β same model β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Stage 3: WCAG Report (format_wcag_report()) β
β JSON β Markdown with severity icons, WCAG links, remediation β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Entrypoint Decision
| Context | File to run | Screenshot source |
|---|---|---|
| Local development | python app/app.py |
Playwright (auto-capture URL) |
| HF Space | python app_space.py |
User uploads PNG |
| Modal | modal_app.py |
User uploads PNG |
| CLI VLM test | python -m vlm.vlm_inference screenshot.png |
Pre-captured PNG |
Package Layout
color_ux_access/ β Core (no Gradio dependency)
color_ux_access/
βββ __init__.py from .cvd_sim import simulate_cvd, CVD_VARIANTS
βββ cvd_sim.py DaltonLens wrapper, 10 types + grayscale
β Public API: simulate_cvd(image, cvd_type) -> PIL Image
βββ capture.py Playwright page β full-page screenshot
Public API: take_screenshot(page, url, timeout=60000) -> PIL Image
vlm/ β Vision Language Model inference
vlm/
βββ vlm_inference.py HF Router β aya-vision-32b (CLI tool + helper fns)
β API: load_model_api(), analyze_image_api()
βββ vlm_inference_llama.py llama.cpp GGUF β local vision model (offline)
β API: load_llama_model(), analyze_image_with_llama()
βββ accessibility_report.py WCAG report generation + markdown formatting
API: AccessibilityReport.generate_report(),
AccessibilityReport.format_report_as_markdown()
app/ β Local dev Gradio app
app/
βββ app.py gr.Blocks β URL input β Playwright screenshot β CVD β VLM
βββ custom_theme.py ColorUXAccessTheme (accessible blue/gray, Inter font)
VLM backends (MODELS dict in app.py)
| Key | Model | Params | Prize |
|---|---|---|---|
aya-vision-32b |
CohereLabs/aya-vision-32b | 32B | Default, Cohere |
minicpm-v-4.6 |
openbmb/mini-cpm-v-4_6 | ~4B | OpenBMB ($5K swap) |
nemotron-15b |
nvidia/Nemotron-4-15B-base | ~15B | NVIDIA (unconfirmed) |
qwen2-vl-7b-gguf |
Qwen2-VL-7B-Instruct GGUF | ~7B | llama.cpp offline |
VLM Prompt System
The VLM receives a structured prompt instructing it to return WCAG-specific JSON:
You are an accessibility expert specializing in colorblind user experience.
Analyze screenshots for WCAG 2.1 compliance issues.
For each finding, cite the specific success criterion (1.1.1, 1.4.1, 1.4.3, or 1.4.11).
Output a JSON object with this structure:
{
"findings": [
{
"type": "Low Contrast | Color Only Information | Missing Text Alternative | Insufficient Non-Text Contrast",
"wcag_criterion": "1.4.1 | 1.4.3 | 1.1.1 | 1.4.11",
"description": "...",
"severity": "critical | serious | moderate",
"location": "Top-left, center, etc."
}
],
"summary": "Overall assessment",
"passes": true/false
}
Expected response fields: type, wcag_criterion, description, severity, location, summary, passes.
CVD Simulation Internals
# color_ux_access/cvd_sim.py
from daltonlens import simulate
import numpy as np
from PIL import Image
# Singleton simulator (lazy init)
_simulator = simulate.Simulator_Machado2009()
_DEFFICIENCY_MAP = {
'deuteranopia': simulate.Deficiency.DEUTAN,
'protanopia': simulate.Deficiency.PROTAN,
'tritanopia': simulate.Deficiency.TRITAN,
}
_SEVERITY_MAP = {
'deuteranopia': 1.0, # dichromacy β full deficiency
'deuteranomaly': 0.6, # anomalous trichromacy β partial
}
def simulate_cvd(image, cvd_type='deuteranopia') -> Image.Image:
if cvd_type == 'achromatopsia':
return _grayscale(image)
deficiency = _DEFFICIENCY_MAP[cvd_type]
severity = _SEVERITY_MAP[cvd_type]
im_np = np.array(image, dtype=np.uint8)
result_np = _simulator.simulate_cvd(im_np, deficiency, severity)
return Image.fromarray(result_np)
Achromatopsia is grayscale via Rec.709 luma coefficients, not a DaltonLens simulator.
Gradio 6 Compatibility
In Gradio 6, theme and css are launch() parameters, NOT Blocks() constructor parameters.
# β
Correct (Gradio 6)
with gr.Blocks(title='Color-UX-Access') as demo:
...
demo.launch(
theme=gr.themes.Base(primary_hue='blue', secondary_hue='gray'),
css=":root { --color-primary: #1E88E5; }",
)
# β Wrong (Gradio 5 pattern β will break in Gradio 6)
with gr.Blocks(title='Color-UX-Access', theme=custom_theme, css="...") as demo:
...
Test: pytest tests/test_app_space.py::test_blocks_theme_not_in_constructor -v
WCAG Standards Referenced
| Criterion | Name | What it covers |
|---|---|---|
| 1.4.1 | Use of Color | Color cannot be the only means of conveying information |
| 1.4.3 | Contrast (Minimum) | 4.5:1 normal text, 3:1 large text |
| 1.4.6 | Contrast (Enhanced) | 7:1 normal text, 4.5:1 large text |
| 1.4.11 | Non-text Contrast | 3:1 for UI components and graphical objects |
See also: docs/DEPLOYMENT.md for HF Space and Modal specifics,
docs/EVALUATION.md for sponsor prize matrix and model-swap details.