Configuration file
One shotlist.config.yaml in the project root, or a file named with --config. Every path in it resolves from the file's own folder.
A key the schema does not know is refused rather than ignored. Before 0.4.0 site.viewpoint: 3 did nothing at all, which looks exactly like a setting that has no effect.
site
| Key | Default | Effect |
|---|---|---|
url | required | Where the site is running |
serve | — | Command that starts the site when nothing answers at url |
allow | [] | Extra network destinations the project approves |
viewport | 1280 × 800 | Browser size |
scale | 2 | Device pixel ratio |
theme | light | light, dark or no-preference |
reducedMotion | true | Disable animation before capture |
ready | — | Selector awaited after each navigation |
settle | 0 | Extra milliseconds to wait after ready |
timeout | 15000 | Milliseconds a step or query may take |
sessions | {} | Signed-in browser states by name |
site.allow
site:
allow:
- assets.example.com
- '*.payments.example.com'
- http://localhost:4400
- wss://events.example.com A bare host means HTTPS port 443. *.example.com means its HTTPS subdomains but not example.com itself. HTTP, WebSocket and non-default ports use a full destination. Each approval matches its protocol, host and port. HTTP and WebSocket connections use separate entries. An --untrusted Run ignores this list and site.url.
site.serve
A string is the command. A mapping accepts:
| Key | Default | Effect |
|---|---|---|
command | required | The program and its arguments; run without a shell |
ready | site.url | A URL, a port, or { log: <pattern> } |
cwd | the config file's folder | Where to run the command |
env | {} | Environment added to the run's |
timeout | 30000 | Milliseconds to wait for it to answer |
site.sessions
A bare path, or a mapping. Files are written by --login and are never edited by hand.
site:
sessions:
admin: .shotlist/admin.json
reader:
path: .shotlist/reader.json
verify: '[data-signed-in]'
keep: [accounts.google.com] | Key | Default | Effect |
|---|---|---|
path | required | Where the session file is written and read |
verify | — | Selector present only on a signed-in page |
keep | [] | Hosts whose cookies the file keeps besides this site's own |
A session file holds the cookies and local storage for the host in site.url. keep adds credential hosts; it does not approve a network destination. See what a session file holds. An --untrusted Run loads no session.
paths
| Key | Default | Contains |
|---|---|---|
recipes | screenshots/recipes | Recipe files |
macros | screenshots/macros | Macro files |
data | screenshots/data | Data files |
out | screenshots/out | Images written by a run |
image
| Key | Default | Effect |
|---|---|---|
format | png | png, jpeg or webp |
quality | 90 | 1–100, for the lossy formats |
Files are named for the format: .png, .webp, and .jpg for jpeg. AVIF is not available. A recipe may override both keys.
install
A mapping of names to folders. A recipe names one of these under its own install key, and --install copies the image there.
finders
Named query templates, called from a recipe by name. $1 and $2 stand for the arguments.
finders:
listRow:
css: 'li, div'
contains: $1
matching: '\$\d'
maxChildren: 12
pick: smallest allowEnv
A list of variable names a recipe may read as ${env.NAME}, so a project that always signs in the same way does not repeat --allow-env on every run. Names only — the values stay in the environment and never enter the configuration.
allowEnv:
- ADMIN_PASSWORD
- READER_PASSWORD It adds to --allow-env and SHOTLIST_ENV rather than replacing them, and SHOTLIST_ENV_DENY is subtracted from the result. An --untrusted run ignores it exactly as it ignores site.allow: a configuration nobody vouched for does not choose what it may read.
deny
File or folder names this project will not read, write or open. Each entry matches one segment of a path, and * stands for any run of characters. Checked against filesystem paths and URL paths.
deny:
- fixtures
- '*.sqlite' check
| Key | Default | Effect |
|---|---|---|
threshold | 0.002 | Fraction of pixels that may differ |
tolerance | 8 | How far one channel may move, out of 255 |
style
Every drawing constant, with its default. Sizes are in image pixels and do not change with scale. A recipe may override any of these under its own style key.
style:
color: '#DC2626'
canvas: '#FFFFFF'
box: { width: 6, radius: 10, pad: 8 }
arrow: { shaft: 6, headHalf: 19, headLength: 38 }
label:
font: 'Arial, Helvetica, sans-serif'
weight: 700
size: 44
fill: '#FFFFFF'
stroke: '#DC2626'
strokeWidth: 6
gap: 40
number:
radius: 26
size: 40
fill: '#DC2626'
text: '#FFFFFF'
mask:
fill: '#94A3B8' | Key | Applies to |
|---|---|
color | Boxes, arrows and discs |
canvas | Space added around the image for labels |
box.width, box.radius, box.pad | The outline drawn around a mark |
arrow.shaft, arrow.headHalf, arrow.headLength | The arrow from a label to a box |
label.font, label.weight, label.size | Label typeface |
label.fill, label.stroke, label.strokeWidth | Label glyphs and their outline |
label.gap | Distance from the label to the box |
label.fontUrl | Stylesheet or font file to load before drawing |
number.radius, number.size | Numbered disc and its numeral |
number.fill, number.text | Disc color and numeral color |
mask.fill | What a masked region is painted with |
label.stroke and number.fill default to color. strokeWidth is centered on the glyph outline, so half of it is hidden under the fill.