# Config format Each device has one YAML file, e.g. `configs/dev.yml`. The **filename without `.yml`** is the config name — it's what a device sends as its `uuid` when it requests `/paper`, and what you pass to the `todays_paper` CLI. A config has four top-level sections. ## `settings` ```yaml settings: timezone: Europe/Stockholm ``` | Key | Description | | --- | --- | | `timezone` | An IANA timezone name. Used for scheduling (see below) and for the `timestamp`/`tomorrow` values templates receive. | ## `sources` Named data sources a template can pull from with `source("name")`. Each entry picks a registered `DataSource` by name and passes it a `params` dict, which becomes that source's attributes (e.g. `self.url`, `self.lat` — see {doc}`../data-sources/index` for what each source type expects): ```yaml sources: weather: source: weather.yr params: lat: 55.64277 lon: 13.20638 altitude: 17 school_work: source: calendar.ical params: url: https://cal.vklass.se/....ics ``` A source is instantiated once per config load and reused across every screen render — `.fetch()` is called fresh each time a template calls `source(...)`, so a source that hits a network API does so on every render, not once at startup. ## `screens` ```yaml screens: width: 1448 height: 1072 rotate: 0 family_calendar: template: home/family_calendar.xml.jinja weather: template: weather.xml.jinja ``` | Key | Description | | --- | --- | | `width`, `height` | The panel's resolution in pixels. Required — rendering fails without them. These are handed to every template as the `width`/`height` variables, and this is also what the root `` element's size is always taken from (see {doc}`../widgets/layout`); a `width`/`height` written directly on `` in the template is ignored. Use `1024`×`758` for an `ED060XC3` panel, `1448`×`1072` for an `ED060KC1` panel (see the firmware's `screen.h`). | | `rotate` | Degrees to rotate the final composited image (e.g. `90`/`180`/`270`), applied after the template has rendered at `width`×`height`. Use this rather than swapping `width`/`height` if a panel is mounted rotated relative to how the template is authored. | | Any other key | A screen name → `{template: }`. The path is resolved relative to `CONFIG_DIR` (see {doc}`../installation`'s note on the storage backends) — `home/family_calendar.xml.jinja` means `configs/home/family_calendar.xml.jinja` under local storage. | ## `scheduler` A weekly timetable of which screen name is "current" at any given moment: ```yaml scheduler: - days: [1, 2, 3, 4, 5] hour: 7 screen: family_calendar - days: [6, 7] hours: [9, 14] screen: weather ``` Each rule is `{days: [...], hour: N | hours: [N, ...], screen: }`. `days` uses ISO weekday numbers (`1` = Monday … `7` = Sunday). Use `hour` for a single trigger time or `hours` for several. The server picks whichever rule's next occurrence is soonest without being in the past, re-evaluating shortly before each scheduled change (see the `Runner`/`Scheduler` classes in {doc}`../api/index` for the exact mechanics) — so a screen effectively stays up until the next rule's time arrives, in whatever order the rules fire across the week. This section is ignored when a screen is picked explicitly via the CLI's `-s` flag (there's no equivalent override on the HTTP API — a device always gets whatever the scheduler says is current).