Screenshots
Take screenshots with a script, in English and Amharic, and keep them current.
Every screenshot on this site is taken by a script, not pasted in by hand. That makes them the same size and style everywhere, gives each one an English and an Amharic version, keeps sensitive data out, and lets you find out when one has gone out of date.
How it fits together#
- A shot list in
smarterp_docs/shots/says what to capture: the page, the steps, the languages, the alt text and the caption. smarterp_docs/tools/shots.pyopens a real browser, follows the steps, and writes PNG files tostatic/img/and a record of each one tostatic/img/manifest.json.- A page shows an image by its asset id, on a line of its own.

The site chooses the image for the reader's language, and a dark version when there is one. The alt text and the caption come from the manifest, in both languages.
Set up once#
You need Python 3 and a browser that Playwright can drive:
pip install playwright
playwright install chromium
Take the screenshots#
python3 smarterp_docs/tools/shots.py
The script starts the documentation preview itself, so nothing else has to be running. It prints each file it writes, its size, and any problem. It exits with an error if anything failed, so it is safe to use in an automated check.
| Option | What it does |
|---|---|
--only ID | Take only this asset. Repeat it for several. |
--lang am | Take only this language. |
--check | Write nothing. Report which images are out of date. |
--list | List the shots and stop. |
--base-url URL | Point the shot lists at another site, such as a SmartERP demo database. |
--optimise | Recompress each PNG without loss. Needs Pillow. |
--prune | Delete image files the manifest no longer lists. |
Write a shot list#
A shot list is a JSON file in smarterp_docs/shots/. This one takes two images, English and Amharic, of the home page:
{
"base": "preview",
"defaults": {"viewport": [1280, 760], "languages": ["en", "am"], "themes": ["light"]},
"shots": [
{
"id": "docs-home",
"url": "/docs/{lang}",
"steps": [{"wait_for": ".card"}],
"annotate": [
{"target": ".search", "text": {"en": "Search box.", "am": "α¨ααα α³α₯αα’"}}
],
"alt": {"en": "The documentation home page.", "am": "α¨αααͺα«α ααα» αα½α’"},
"caption": {"en": "The home page.", "am": "ααα» αα½α’"}
}
]
}
| Field | Meaning |
|---|---|
id | The asset id: lower-case letters, digits and single hyphens. |
url | The page to open. {lang} becomes en or am. |
steps | Things to do first, each with one key: goto, click, hover, fill, press, wait_for, wait, scroll_to. |
capture | "viewport" (the default), "full_page", or {"selector": ".callout"} for one element. |
mask | Selectors to blur before the picture is taken. |
annotate | Elements to outline and number. The text of each becomes a numbered list under the picture. |
themes | ["light"], or ["light", "dark"] to also take a dark version. |
alt, caption | Required in every language. |
A value in a step can differ by language, for example {"fill": [".search input", {"en": "approval", "am": "αα½α°α
"}]}. It can also read an environment variable, as in $ENV:ODOO_PASSWORD, so a password never sits in a file.
What the script protects you from#
- No image without words. A shot without alt text or a caption in both languages is refused before a browser starts, and the content tests fail if a page uses an image that has none.
- No secrets. Before each picture the script reads the visible text. An email address outside the allowed domains, an API key, a token, a password or a phone number stops that image from being saved, and the run fails. The rules are in
shots/_policy.json. Anything inmaskis blurred and left out of the scan. - A size limit. An image over 250 KB is reported, so pages stay light on a slow connection.
- Files that match the record. The tests check that every file in
static/img/is in the manifest, that its checksum and size still match, and that every image a page shows exists.
Warning
Take screenshots only from demo data, never from a live system with customer names, prices or staff details. The scan catches common patterns, not everything a person would recognise.
Keep them current#
Run the check after a change to the screens:
python3 smarterp_docs/tools/shots.py --check
For each language it reopens the page and compares what is on it with what was there when the picture was taken. An image that no longer matches is reported as stale. Take it again, look at it, and commit the new file with the manifest.
Screens from SmartERP itself#
The shot lists that ship with this module capture the documentation site. To capture SmartERP's own screens, such as the approval queue, point a shot list at a running SmartERP that holds demo data, and sign in with steps that read the account from the environment:
ODOO_USER=demo ODOO_PASSWORD=... python3 smarterp_docs/tools/shots.py --base-url http://localhost:8069
Use only SmartERP's own screens and this site. Never show another company's product or brand.
Checklist#
- The shot list has alt text and a caption in English and Amharic, and an editor who reads Amharic has checked the Amharic.
python3 smarterp_docs/tools/shots.pyfinishes with no problem.- You have looked at every image, in both languages.
- The page shows the image by its asset id, in both languages, at the same place.
python3 smarterp_docs/tools/run_offline_tests.pypasses.