A TYPO3 extension that runs automated accessibility audits against your site's pages using axe-core via Playwright. The scanner runs in a self-contained Docker image built on top of Microsoft's official Playwright image, so no Node.js or browser setup is required on the host.
- Docker or Podman
composer require surfcamp/surfa11yAfter installation, activate the extension and flush the cache:
ddev typo3 cache:flushThen build the scanner image:
docker build -t surfcamp/surfa11y-scanner packages/surfa11y/This builds the Docker image (surfcamp/surfa11y-scanner) locally from the bundled Dockerfile.
The image is based on mcr.microsoft.com/playwright and installs the required npm packages on top — no image registry or maintenance required.
Then you may run:
ddev startInside the .ddev directory you can create a docker.compose.surfa11y.yml which defines the axe-core-scanner-server service. When DDEV starts, it will automatically build the Docker image for the scanner if it doesn't exist and start the container. The scanner server will be available on port 3000 of the DDEV environment. DDEV will build the docker image for the axe-core-scanner-server and open a port on 3000
services:
surfa11y-scanner:
image: surfcamp/surfa11y-scanner
build:
context: ${DDEV_APPROOT}/packages/surfa11y
expose:
- "3000"
restart: unless-stoppedThis uses the build in ScanCommand that can be executed over DDEV with
ddev typo3 surfa11y:scan "https://typo3.org,https://google.com"Or directly with Docker when TYPO3 runs locally (scanner in a container):
# Start the scanner container
docker run -d --name surfa11y-scanner -p 3000:3000 surfcamp/surfa11y-scanner
# Run the scan — point TYPO3 at the exposed
scanner port
SURFA11Y_SCANNER_URL=http://localhost:3000 vendor/bin/typo3 surfa11y:scan "https://typo3.org,https://google.com"Or when both TYPO3 and the scanner run in Docker containers on the same network:
# Create a shared network
docker network create surfa11y-net
# Start the scanner on that network
docker run -d --name surfa11y-scanner --network surfa11y-net surfcamp/surfa11y-scanner
# Connect your TYPO3 container to the same network (if not already)
docker network connect surfa11y-net <your-typo3-container>
# Run the scan — the default scanner URL (http://surfa11y-scanner:3000) resolves via Docker DNS
docker exec <your-typo3-container> php vendor/bin/typo3 surfa11y:scan "https://typo3.org,https://google.com"The scanner launches a headless Chromium browser, navigates to each URL, and runs an axe-core analysis. All pages are
scanned in parallel. Results are written to stdout as a JSON array.
A HTTP Server is started on port 3000, which
can be used to trigger scans via POST requests with a JSON body containing the urls array.
One object per URL:
| Field | Description |
|---|---|
url |
The scanned URL |
violations |
Accessibility rules that failed |
passes |
Rules that passed |
incomplete |
Rules that could not be fully evaluated |
error.message |
Set if an error occurred |
error.stack |
Stack trace if an error occurred |
Each rule entry contains an id, impact, description, helpUrl, tags (e.g. wcag2a, wcag412), and a nodes
array pointing to the affected DOM elements.
Pages added to the scan queue are processed one at a time by:
ddev typo3 surfa11y:work-page-queuePHPUnit is included as a dev dependency. Run the test suite from the project root:
ddev exec ./vendor/bin/phpunit --testdox