Automatic Screenshots¶
The documentation supports automatically generated screenshots that are updated via a CI pipeline on every pull request. Screenshots are captured via a Selenium browser (Chrome) directly from the running application.
Screenshot Directive¶
To request a screenshot in a Markdown file, an HTML comment with the screenshot parameters is inserted:
<!-- screenshot: admin-inventarliste route=/index-test.php?r=inventory/admin selector=#inventory-grid role=admin -->

Parameters¶
| Parameter | Required | Default | Description |
|---|---|---|---|
route |
Yes* | — | URL path relative to BASE_URL |
selector |
No | body |
CSS selector to wait for |
role |
No | admin |
Login role: admin or user |
fullpage |
No | false |
Full page or viewport only |
width |
No | 1440 |
Viewport width in pixels |
height |
No | 900 |
Viewport height in pixels |
delay |
No | 500 |
Wait time in ms after selector is found |
*route can be defined in the manifest file.
ID Conventions¶
- Only letters, digits, hyphens, and underscores:
a-z,A-Z,0-9,-,_ - Recommended scheme:
<area>-<page>[-<detail>] - Examples:
admin-inventarliste,user-dashboard,admin-einstellungen-regeln
Manifest File¶
For reusable or centrally managed screenshots, the file
docs/screenshots.manifest.yml is available:
screenshots:
admin-inventarliste:
route: "/index-test.php?r=inventory/admin"
selector: "#inventory-grid"
role: admin
Values in the manifest serve as defaults. Inline directives in Markdown override the manifest entries.
Generating Screenshots Locally¶
Prerequisites¶
- Docker (for Selenium Chrome)
- PHP 7.4+ with Composer
- Access to the running application (local or staging)
Step 1: Start Selenium¶
Step 2: Set Environment Variables¶
export BEHAT_BASE_URL=http://localhost:8080
export SELENIUM_URL=http://localhost:4444/wd/hub
export BEHAT_USER=admin@calhelp.de
export BEHAT_PASS=admin
# Optional for "user" role:
# export BEHAT_FRONTEND_USER=user@example.com
# export BEHAT_FRONTEND_PASS=userpass
Credentials
Never check credentials into version control. Use environment variables exclusively.
Step 3: Generate Screenshots¶
Output Directory¶
Generated screenshots are placed under docs/assets/screens/:
docs/assets/screens/
├── admin-inventarliste.png # Current screenshot
├── admin-inventarliste.prev.png # Backup of the previous screenshot
└── .gitkeep
When overwriting an existing screenshot, the old one is automatically
backed up as <id>.prev.png.
CI Pipeline¶
The GitHub Actions workflow file .github/workflows/docs-screenshots.yml is
automatically triggered on pull requests when Markdown files under docs/
or the manifest file are changed.
Workflow¶
- PR with Markdown changes is created
- Workflow starts Selenium Chrome as a service container
- Behat suite
docsis executed - Generated/updated screenshots are committed to the PR branch
- The commit contains
[skip ci]to prevent infinite loops
Infinite Loop Protection¶
Three protection mechanisms:
github.actor != 'github-actions[bot]'— Job is skipped for bot commits[skip ci]in the commit message — GitHub Actions does not start a new runpaths:filter — only.mdfiles and the manifest trigger the workflow
Required GitHub Secrets¶
| Secret | Description | Status |
|---|---|---|
BEHAT_USER |
Admin username | Existing |
BEHAT_PASS |
Admin password | Existing |
DOCS_SCREENSHOT_BASE_URL |
URL of the staging instance | Create new |
BEHAT_FRONTEND_USER |
Frontend username | Create new |
BEHAT_FRONTEND_PASS |
Frontend password | Create new |
Security¶
The screenshot runner contains several security mechanisms:
- Route blacklist: URLs containing
/logout,/delete,/remove,/destroy, etc. are blocked - Relative URLs only: External URLs are rejected
- Destructive elements disabled: After loading, every link/button with dangerous text (Delete, Remove, Logout, etc.) is disabled via JavaScript
- No clicks on unknown links: Navigation occurs exclusively via direct URL calls