Reference

Module Reference

Exhaustive per-module option tables for every built-in module. If you're new to the module system, start with the Modules guide, this page assumes you already know which module you want and are looking for the exact field names.

Home Screens includes 45 built-in modules organized into 9 categories. Each module can be dragged onto the canvas from the module palette in the editor.

One of those categories, Health & Fitness, has no built-in modules yet. It is reserved for add-ons such as Strava and Garmin, stays hidden in the module palette until you install one, and so has no section below.

Where a module has a refreshIntervalMs option, its default comes from that module's fetch cache lifetime rather than a value written into the module itself, so it stays in step with how long the server caches the same data. The numbers below are the current defaults; you can always override them per module.

Full Screen

These modules are designed to fill the entire display as ambient, always-on screens. They use the fillsCanvas flag, position, size, and style controls are hidden in the editor since the module always occupies the full display area.

Themes: all five full-screen modules share one theme field with twelve color palettes: linen, paper, mist, sandstone, vellum, and bloom (light), charcoal, midnight, slate, aurora, obsidian, and horizon (dark). Leave theme unset to inherit the display-wide default from Settings > Screen (fullscreenTheme). Anything that isn't one of the twelve ids falls back to Linen.

The six newer themes (sandstone, vellum, bloom, aurora, obsidian, horizon) additionally carry their own accent color and, on the Full-Screen Calendar only, an event style deciding how event blocks are painted: a faint tint (linen and the other original themes), a translucent card, a solid color fill, or a plain surface with a colored edge. All but vellum also paint a static gradient behind the module. On the calendar, chore chart, and meal planner, setting accentColor overrides the theme's own accent and leaving it empty follows the theme; the weather module's accent follows the sky instead, and the photo viewer has none.

The older darkMode boolean on Full-Screen Calendar and Full-Screen Chore Chart has been superseded by theme and is no longer shown in the editor. It still works as a fallback so older configurations keep rendering: darkMode: true maps to charcoal and false maps to linen. It is ignored entirely whenever theme is set.

Full-Screen Calendar

A fullscreen ambient calendar display inspired by Skylight, designed to fill the entire screen. Automatically sizes to the display dimensions and pins to position (0,0). Pulls from any iCal feed, Google Calendar (via iCal URL or OAuth), or iCloud (app-specific password), see Calendar setup.

Type fullscreen-calendar · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
viewstring"schedule"Display style: schedule, week-list, month-grid, day-timeline, agenda, family-grid, up-next, free-time, or rolling
densitystring"cozy"Layout density: cozy or snug
typographySizestring"medium"Text size: small, medium, large, extra-large, 2x-large, 3x-large, or 4x-large
accentColorstring""Accent color for event indicators and highlights. Leave empty to follow the theme's own accent; set a color to pin it
dimPastEventsbooleantrueReduce opacity of past events
shadeWeekendsbooleantrueSubtle background tint on weekend columns, rows, or (rolling view) cells
showWeatherbooleanunsetSuperseded by weatherPlacement. Kept so older configurations still render: false maps to off, true to header
weatherPlacementstring"header"Where weather appears: off, header (temperature pill at the top), days (daily forecast on day headers), events (forecast for each event's start time), or days-and-events. Day placement renders in the schedule, week list, and agenda views; event placement in week list and agenda. Views without that surface fall back to the header pill, so weather never disappears when switching views
showNowLinebooleantrueShow a line indicating the current time
sourceFilterarrayunsetCalendar source IDs to display (empty = all)
titleFilterobjectunsetKeyword filter on event titles: { mode, terms } where mode is include (keep only matching events) or exclude (drop them). Terms are case-insensitive substrings; an empty terms list means no filter
darkModebooleanfalseSuperseded by theme (see above). Kept so older configurations still render
themestringunsetOne of the twelve shared full-screen palettes (see Themes above). Unset = inherit the display default from Settings > Screen
todayHighlightStylestring"full"How strongly today is highlighted: full (accent-tinted fill), subtle (faint background), minimal (marker only), or off
eventOverlapstring"columns"How overlapping events are laid out in schedule and day timeline views: columns (side-by-side, with a "+N" indicator when events don't fit) or stacked (cascading overlap)
wrapEventTitlesbooleanfalseWrap long event titles onto a second line in schedule and month views instead of truncating
eventTapDetailsbooleanfalseOn touch displays, tap an event to open a detail panel with its time, location, and description
eventTapStylestring"sheet"How the event detail opens: sheet (slides up from the bottom) or card (centered card)
startDaystring"sunday"First day of the week (sunday or monday) for every view laid out by week: the week list, month grid and family grid, the schedule's start-of-week anchor, and the agenda's week separators
showCountdownbooleanfalseWeek list and agenda views: show a "in 2 hours" style countdown next to upcoming events
showProgressBarbooleanfalseWeek list and agenda views: show a progress bar on events happening right now
countdownAllDaybooleanfalseAlso show day countdowns on all-day events (off by default so "in 0 days" noise never appears)
emptyDayTextstring""Custom wording for days with no events (for example "Free day!"); empty = the standard message
hourWindowstring"fixed"Schedule and day timeline hours: fixed (the start and end hours below) or rolling (a window that follows the clock, starting an hour before now, so what is next is always full size; a footer strip names the window and counts today's earlier events it is not showing)
rollingHoursnumber8Length of the rolling window in hours (4–16)
scheduleDaysToShownumber0Days visible in schedule view (1–7, 0 = auto)
scheduleHourStartnumber6Schedule view start hour (0–23)
scheduleHourEndnumber22Schedule view end hour (1–24)
scheduleShowDescriptionbooleanfalseShow the event description under the title in schedule view
scheduleStartAnchorstring"today"First column of the schedule view: today (slides forward each day), start-of-week (days keep their place all week), or next-weekend (Saturday and Sunday planning board)
weekCollapsePastDaysbooleantrueCollapse past days in week list view
weekShowDescriptionbooleanfalseShow the event description under the title in week list view
showMealsbooleanfalseWeek list view: add the day's planned meals from the meal planner under its events
showChoresbooleanfalseWeek list view: add one chore progress row per day (done/total, a bar, and who has a chore) from the chore chart
familyShowEveryoneRowbooleantrueFamily grid view: an Everyone row for events on calendars that belong to nobody in particular
familyShowDescriptionbooleanfalseFamily grid view: show the first two lines of the event description under each title
rollingWeeksToShownumber6Rolling weeks view: how many weeks to show (1–8), always starting with today in the top-left
upNextLaterCountnumber3Up next view: how many more events from the same day to list under the big one (0–6)
upNextShowEarlierbooleantrueUp next view: list today's running and finished events
upNextShowTomorrowbooleantrueUp next view: list tomorrow's events
upNextShowDescriptionbooleanfalseUp next view: show the event description on the big card and under each listed event
freeTimeHourStartnumber7Free time view start hour (0–23)
freeTimeHourEndnumber22Free time view end hour (1–24)
freeTimeShowTomorrowbooleantrueFree time view: add a compact row per person for tomorrow
monthShowWeekNumbersbooleanfalseShow week numbers in month grid view
monthMaxEventsPerCellnumber0Max events per cell in month grid (0 = auto)
dayHourStartnumber6Day timeline view start hour
dayHourEndnumber22Day timeline view end hour
dayShowLocationbooleantrueShow event locations in day timeline view
dayShowDescriptionbooleanfalseShow the event description under the title in day timeline view
agendaDaysAheadnumber14Days ahead to show in agenda view (7–30)
agendaHideEmptyDaysbooleanfalseHide days with no events in agenda view
agendaShowFinishedTodaybooleanfalseAgenda view keeps events that already ended today on the list (dimmed) until midnight instead of dropping them as they end
agendaShowDescriptionbooleanfalseShow the event description under the title in agenda view
agendaSeparatorsstring"none"Boundary markers in agenda view: none, weeks (a "Week of" rule at each week start), or weeks-and-months (plus a month divider; the month marker wins when both land on the same day)
showLegendstring"off"A color key naming each calendar the module is showing: off, header, or footer
showNameTagsbooleanunsetName tags: put the owning family member's initials, in their color, where the calendar dot goes. Who owns which calendar is set in Settings > Calendar > People. Calendars nobody owns keep a plain dot
legendModestringunsetWhat the color key lists: calendars (one row per calendar), people (one avatar per family member who owns a calendar with an event in view, plus Everyone for shared calendars) or groups (one row per family group as a stack of avatars, then members in no group, then Everyone)
peopleFilterobjectunsetShow only these people: family member ids and family group ids. Groups are expanded and people are mapped to their calendars when the screen renders, so adding someone to a group updates every screen that shows it. Applies together with sourceFilter
eventRulesarrayunsetRestyle or hide individual events by what they match. See Event and day rules below
dayRulesarrayunsetTint whole days and add badges to them. See Event and day rules below

In the schedule and day timeline views, descriptions only draw when the event block is tall enough to fit them, so short events show the title alone even with the toggle on.

The up next view is a fixed box, so when descriptions would push its last row off the bottom, the listed events drop theirs first, then the big card, until everything fits. In the family grid a cell only reserves room for the descriptions its events actually have, so plain events still fit next to described ones.

View details:

  • schedule: Multi-day time grid with events positioned by start/end time. Shows a "now" line and supports configurable hour range.
  • week-list: Day-by-day vertical list of the current week's events with collapsible past days.
  • month-grid: Traditional month calendar grid with event dots/names in each cell and today highlighted.
  • day-timeline: Single-day vertical timeline with event blocks, location details, and hour markers.
  • agenda: Scrollable list of upcoming events across multiple days, grouped by date.
  • family-grid: People as rows, the week as columns. Each person set up under Settings > Family gets a row; events on calendars that belong to nobody sit once on an Everyone row. Without people, every calendar with an event this week gets its own row.
  • up-next: The next event, big: title, time, place, countdown (or progress while it is running), then short lists for later today, earlier today, and tomorrow.
  • free-time: One track per person for today, busy blocks and free gaps side by side, with a card naming when everyone is free. Events on shared calendars count as busy for the whole household.
  • rolling: The next few weeks as a grid whose top-left cell is always today. Weekday columns shift one left each midnight, weekends are shaded, and each new month is marked on its first day. rollingWeeksToShow sets the week count (1–8, default 6).

People: the family grid and free time views read the household list under Settings > Family. Choose each person’s calendars under Settings > Calendar > Whose calendars? A calendar picked for nobody is shared.

Full-Screen Chore Chart

A fullscreen ambient chore chart display designed to fill the entire screen. Reads members from data/family.json and chores from data/chores.json so the fullscreen display, module views, and remote Chores tab all share the same source of truth. Automatically sizes to the display dimensions and pins to position (0,0).

Type fullscreen-chore-chart · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
viewstring"chores"Display mode: chores (daily chore board), rewards-store (browse and redeem rewards), or one of the read-only reward histories: reward-history (day by day), reward-totals (30-day totals over a list) or reward-spotlight (the newest reward up top)
showRewardsButtonbooleanfalseShow a toggle button in the chore board header to switch to the rewards store view
weekStartDaystring"monday"First day of week: sunday or monday
weekProgressstring"chips"Where the week's stars render. Omitted = chips. One of chips, strip, grid, off
layoutstring"by-time"Group chores by: by-time (one row per chore, a dot per person, with the person's name under each dot when the row has room) or by-person (one section per person with their own chores). By person works best for up to four people
showPointsbooleantrueShow ticket values for chores
showStreaksbooleantrueShow completion streaks
showTimeOfDaybooleantrueGroup chores by time of day (morning, afternoon, evening); by person, this only orders each person's chores
allowDisplayCompletebooleantrueLet anyone tap a chore on the display itself to mark it done
darkModebooleantrueSuperseded by theme (see above). Kept so older configurations still render
densitystring"cozy"Layout density: cozy or snug
typographySizestring"medium"Text size: small, medium, large, extra-large, 2x-large, 3x-large, or 4x-large
accentColorstring""Accent color for highlights and active time-of-day. Leave empty to follow the theme's own accent; set a color to pin it
themestringunsetOne of the twelve shared full-screen palettes (see Themes above). Unset = inherit the display default from Settings > Screen

Layout details:

  • Portrait: Header with date and completion percentage, horizontal member chips with progress bars, stacked time-of-day bands (morning/afternoon/evening/anytime), and a star chart grid at the bottom for weekly tracking. By person, the chips give way to one section per person.
  • Landscape: Top bar with date and member chips, one column per time of day (or per person), and a horizontal star chart in the footer.
  • Only people with a chore today get a chip. Someone with chores on another day of the week is named in a "Day off" line under the chips; someone with no chores at all this week is left off the chart.

Rewards store view:

The rewards-store view displays a fullscreen rewards browsing and redemption interface. A member picker at the top shows each member's ticket balance. The main area shows a grid of available rewards with ticket costs and eligibility indicators. Members can redeem rewards directly from the display when they have enough tickets. When showRewardsButton is enabled, a toggle button in the chore board header lets users switch between the chore board and rewards store without changing the module config.

Reward history views:

Three read-only views of what the family has redeemed, newest first, covering the 90 days the hub keeps. When the history runs past the screen the list scrolls by touch and says how many more are below.

  • reward-history: Grouped under Today, Yesterday, This week and Earlier. Each row leads with the reward, with the person under it.
  • reward-totals: Three tiles for the last 30 days (tickets spent, rewards redeemed, the family's favorite) over a one-line list, which fits the most history. The rewards store's History button opens this view and returns to the store after a minute without a touch.
  • reward-spotlight: The newest redemption as a large card, with the rest listed under it.

Full-Screen Meal Planner

A fullscreen ambient meal planner display that shows the weekly meal schedule at a glance. Reads from the same meal data as the standard meal planner module. Supports light/dark themes with multiple color palettes.

Type fullscreen-meal-planner · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
viewstring"week"Display style: week, today, menu-board, or next-meal
densitystring"cozy"Layout density: cozy or snug
typographySizestring"medium"Text size: small, medium, large, extra-large, 2x-large, 3x-large, or 4x-large
accentColorstring""Accent color for highlights. Leave empty to follow the theme's own accent; set a color to pin it
showPrepTimebooleantrueShow prep time in minutes
showTagsbooleantrueShow meal tags
showEmojibooleantrueShow meal emoji
showDifficultybooleanfalseShow difficulty indicator
themestringunsetOne of the twelve shared full-screen palettes (see Themes above). Unset = inherit the display default from Settings > Screen
tapRecipeActionstring"off"What tapping a meal with a saved recipe link does: off, qr (fullscreen QR code overlay), or iframe (embed the recipe page)
showTitlebooleantrueShow the view title ("Today's Meals", "This Week's Meals", "Today's Menu")

Enabled slots, week start day, default slot times, and 12/24h formatting are household-level settings stored in data/meals.json: edit them once under /remote > Meals > Settings and every meal-planner module on every display picks up the change. The time format defaults to the household Time format setting (Settings → Defaults → Location & language); pick an explicit 12- or 24-hour option in meal settings only if meals should differ from it.

View details:

  • week: Full 7-day grid with meal cards organized by slot, today highlighted.
  • today: Focused view of today's meals with large cards and details.
  • menu-board: Restaurant-style board layout for displaying the week's menu.
  • next-meal: Large display of the next upcoming meal with context label.

Full-Screen Weather

A fullscreen weather dashboard with six views. Panorama stacks the current conditions, an optional next-hour rain strip, a temperature curve, a 7-day outlook with range bars, and a row of stats. Wide strip is Panorama's parts side by side, for a module that spans the width of a landscape screen but not its height: the current conditions, then the temperature curve over the stats, then the outlook, with the text sized to the module's area rather than its height. In a portrait box the three columns stay, each in a tall form: the hours run down the middle column as rows and each forecast day gets a band of its own. Almanac is a grid of instrument cards: sun arc, moon phase, wind, humidity, pressure, UV, and visibility, plus the next 12 hours. Ambient is a large, plain read for across the room. Week ahead gives each forecast day its own band (or, on a landscape display, its own column) with the day's icon, description, rain chance, wind (when the weather source reports a daily figure), and a high/low bar on a shared scale. Hour by hour draws the next 24 hours as a timeline (48 on sources that report every three hours): a temperature curve through every hour, with rain chance and wind beside it. It runs down the page on a portrait display and across it on a landscape one.

Every view has a portrait and a landscape layout, picked automatically from the display's shape.

The background tint follows the current conditions and the position of the sun, layered behind the cards so it never affects how readable anything is. Set Background tint to Off for a plain themed background.

Some panels depend on what your weather source provides, and hide themselves when it has nothing to show:

  • Next-hour rain needs minute-by-minute data, which only Pirate Weather offers today.
  • Weather warnings need alerts, available from Pirate Weather and NOAA.
  • Pressure and dew point come from NOAA, Open-Meteo, and the Met Office.
  • UV index comes from Pirate Weather, the Met Office, WeatherAPI, and Open-Meteo.
  • Visibility comes from NOAA.

The temperature curve draws however many hours your source returns, and its heading says how many. Most sources give 48 hours; OpenWeatherMap gives 5 days in 3-hour steps; NOAA gives about 6 days hourly.

Type fullscreen-weather · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
viewstring"panorama"panorama, strip (Wide strip), almanac, ambient, week, or hourly
densitystring"snug"cozy or snug. Controls padding, gaps, and chart heights
typographySizestring"medium"Text size. Scales type only, so the layout keeps its proportions. One of small, medium, large, extra-large, 2x-large, 3x-large, 4x-large
accentColorstring""Leave empty to let the accent follow the weather (amber for clear, blue for rain, violet for storms); set a colour to pin it
themestringunsetFull-screen palette; unset inherits the display default
skyLayerstring"auto"auto tints the background by conditions, off uses the plain theme background
animateConditionsbooleantrueFalling rain and snow. Turn off if the display stutters on older hardware
showNowcastbooleantrueNext-hour rain strip (Panorama, Pirate Weather only)
showAlertsbooleantrueSevere-weather banner
showTimebooleantrueClock in the header. Follows your 12/24-hour setting and the display's time zone
showRibbonbooleantrueTemperature curve (Panorama)
showStatRailbooleantrueBottom stats row (Panorama)
daysToShownumber7Days in the outlook list, 3–7 (Panorama and Week ahead)
locationLabelstringunsetOverrides the place name shown in the header

Full-Screen Photo Viewer

A fullscreen digital photo frame that cycles through photos from a local directory, an Immich library, a OneDrive folder, or an iCloud shared album (with Google Photos available as an import), or displays a single pinned photo as a static wallpaper. Supports transitions, shuffle, and an optional clock overlay, and can mix in videos from the same source.

The editor's Mode dropdown toggles between Slideshow and Single Photo. Single-photo mode simply sets the file field; the rotation, interval, transition, and shuffle controls are hidden while file is set. "Single Photo" is only an editor UI label, nothing stores a "mode" setting on the module itself.

Type fullscreen-photo · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
directorystring""Path to local photo directory (slideshow mode)
filestringunsetPath to a single pinned photo. When set, the viewer shows this image statically and ignores directory/intervalMs/transition/shuffle. Shows a "No photo selected" empty state until chosen
intervalMsnumber30000Time between photos in milliseconds
transitionstring"fade"Transition effect: fade, slide, zoom, or none
objectFitstring"cover"Image fit mode: cover, contain, or fill
shufflebooleanfalseRandomize photo order
showClockbooleantrueShow clock overlay on photos
clockBackdropnumberunsetHow solid the backdrop behind the clock overlay is, from 0 (none) to 100 (a solid band behind the clock). Unset = 72 for a light backdrop, 55 for a dark one
clockBackdropColorstringunsetColor of the backdrop behind the clock overlay (hex or rgb()). The clock's text switches to dark or light, whichever reads best on it. Unset = white on light themes and black on dark ones, with the theme's own text colors
kenBurnsbooleanfalseEnable Ken Burns (slow pan/zoom) effect
themestringunsetPalette for the clock overlay and empty states; one of the twelve shared full-screen palettes (see Themes above). Unset = inherit the display default from Settings > Screen, and Midnight if that is unset too
sourcestring"local"Photo source: local, immich (requires keys in Settings > API keys), onedrive (a one-time Microsoft sign-in), or icloud (a public shared album, no keys needed)
immichAlbumIdstringunsetFilter to a specific Immich album
immichPersonIdstringunsetFilter to a recognized person (face) in Immich
immichFavoritesOnlybooleanfalseOnly show photos marked as favorites in Immich
immichCountnumber50Number of photos to load per refresh (10–200)
icloudAlbumUrlstringunsetiCloud shared album link (icloud.com/sharedalbum/#TOKEN) or bare token (iCloud source)
onedriveFolderIdstringunsetOneDrive folder to pull photos from (OneDrive source)
onedriveFolderNamestringunsetFolder name as shown in the editor, display only, the ID above is authoritative
onedriveCountnumber50Number of photos to load per refresh (10–200)
mediaTypesstring"photos"What to show: photos, videos, or both
maxVideoDurationMsnumber60000Longest a video slide can play before moving on (60 sec)

Immich source

The Immich options only appear in the editor when both Immich Server URL and Immich API Key are configured in Settings > API keys. Album and person filters are mutually exclusive, selecting one clears the other.

OneDrive source

The OneDrive option only appears in the Photo Source picker once a Microsoft Application (client) ID is saved in Settings > API keys. Signing in happens in the module itself: click Sign in with Microsoft and enter the shown code at the link on any device. Photos shuffle on every refresh; very large folders use a random sample of 1,000 photos. The full walkthrough is in OneDrive photos.

Full-Screen News

The News Headlines feeds on the whole canvas: one story at a time with its photo, or a newspaper-style front page. Follows the same feed list, shorthands, and filters as News Headlines.

Type fullscreen-news · Default size 1080 × 1920 · fills the whole display

OptionTypeDefaultDescription
viewstring"story"story (one story at a time, its picture filling the top of the screen) or front-page (a lead story plus the next five)
rotateIntervalMsnumber15000Seconds per story, or per front page
showDescriptionbooleantrueShow the story summary
showSourcebooleantrueShow the feed name
showTimestampbooleantrueShow how long ago each story was published
showImagesbooleantrueShow story pictures
showTimebooleantrueClock and date in the corner
typographySizestring"medium"small, medium, large, extra-large, 2x-large, 3x-large, or 4x-large
accentColorstring""Progress bar and pill colour; empty follows the theme
themestringunsetOne of the shared full-screen palettes (see Themes above); unset inherits the display default
feedsarrayone entryFeeds to follow, in order (up to 12). label overrides the name shown as the story source; color tints the source dot; homeNetwork lets the hub read a feed from a device on your own network (a self-hosted reader); maxItems caps stories from that feed before merging
refreshIntervalMsnumber300000How often to fetch new stories (5 min)
maxItemsnumber12Stories to show after merging every feed (3 to 24)
maxAgeHoursnumber0Hide stories older than this many hours; 0 = any age
blockedWordsstring""Comma or newline separated words; a story mentioning any of them in its headline or summary is hidden
requiredWordsstring""Comma or newline separated words; only stories mentioning one of them show
preserveOrderbooleanfalseKeep each feed's own order instead of sorting newest first
tapActionstring"qr"What a tap does on a touch display: qr (a code that opens the story on your phone), details (the summary, with a small code), or none

Time & Date

Clock

Displays the current time with optional date information. Supports 18 visual styles.

Type clock · Default size 640 × 280

OptionTypeDefaultDescription
viewstring"classic"Display style: classic, digital, analog, minimal, flip, word, binary, vertical, split, progress, fuzzy, world, dot-matrix, radial, arc, neon, bar, or elapsed
format24hbooleanfalseThe older per-clock 24-hour toggle. Only read when hourFormat is absent
hourFormatstring"inherit"Where the 12/24-hour choice comes from: inherit follows the display's Time format setting, 12h or 24h pins it for this clock. Clocks from before this option existed have no hourFormat and keep using format24h
showSecondsbooleantrueDisplay seconds
showDatebooleantrueShow date below time
dateFormatstring""Date format string (date-fns); empty shows the whole date the way the household's language writes it
showWeekNumberbooleanfalseDisplay current week number
showDayOfYearbooleanfalseDisplay day of year (e.g. "Day 67 of 365")
timezonestring""IANA timezone to show (e.g. "Asia/Tokyo"); empty = follow the display setting
alignmentstring"center"Where the clock sits across its box: left, center, or right. Unset centers it
verticalAlignstring"center"Where the clock sits down its box: top, center, or bottom. Unset centers it
sizeModestring"fit"How the clock is sized. fit (absent) sizes it off the box height with Text size as a percent of that, and shrinks a one-line view to the box width. fixed renders Text size alone (a percent of the 16px base) and never reads the box, which then only places the clock.
showAmPmbooleanfalseMinimal: append AM/PM in 12-hour mode. Absent = off, so a Minimal clock placed before this existed keeps its bare time.
showNumeralsbooleanfalseShow hour numbers on the analog clock face
animateFlipbooleantrueShow flip animation on digit change (flip view)
accentColorstring"#22d3ee"Accent color used by several views
worldZonesarray[]Additional timezones for the world view (max 3), each with label and timezone
referenceTimestring""ISO timestamp or time string for elapsed view
referenceLabelstring""Label for elapsed view (e.g. "market open", "shift start")
countUpbooleantrueCount up (true) or down (false) from reference time (elapsed view)
elapsedFormatstring"units"How the elapsed view renders units: units (50d 20h 13m), unitsUpper (50D 20H 13M), unitsShort (50day 20hr 13min), colon (50:20:13:00), words (50 days, 20 hours), or wordsTitle (50 Days, 20 Hours). The two word styles are localized.
elapsedPrecisionstring"auto"Which units the elapsed view shows: auto, days, daysHours, daysHoursMinutes, or daysHoursMinutesSeconds. Named precisions always show their full set including zeros; auto hides days and hours while they are zero and shows seconds only under an hour. The colon format is the exception: it always keeps a seconds segment, so its rightmost column always means seconds and the counter never appears to reset at the hour or day mark.

Calendar

Shows upcoming events from any iCal feed, Google Calendar (via iCal URL or OAuth), or iCloud (app-specific password), with multiple view modes.

Type calendar · Default size 540 × 340

OptionTypeDefaultDescription
viewModestring"daily"View mode: daily, agenda, week, multi-week, month, or rolling
daysToShownumber3Number of days ahead to display
showTimebooleantrueShow event times
showLocationbooleanfalseShow event locations
showEventBackgroundbooleantrueDaily and agenda views: show the background surface behind each event row. Defaults to true.
maxEventsnumber20Maximum number of events to display
showWeekNumbersbooleanfalseShow week numbers in week/multi-week/month views
weeksToShownumber6Multi-week and rolling views: how many weeks to show, 2–12 in multi-week (starting with the current week) and 1–8 in rolling (starting today)
gridMaxEventsPerCellnumber4Week/multi-week/month/rolling grids: event pills per day cell before "+N more" (2–10). Unset shows 5 in the week grid and 4 in the shorter multi-week, month and rolling cells
startDaystring"sunday"First day of the week in the week/multi-week/month grids: sunday or monday (the rolling view ignores it; its columns follow today)
gridEventStylestring"classic"Event rendering in the week/multi-week/month/rolling grids: classic (colored dot on a light pill) or colored (see below)
gridEventPillBackgroundbooleanfalseColored style: faint background behind timed events
gridThemestring"banner"Multi-week, month and rolling grid look: banner (the original tinted day strips), clean (month header, quiet day numbers, compact times next to bold titles), minimal (titles only, with a colored edge per calendar), or vivid (solid color pills). The three newer looks style their own events, so gridEventStyle doesn't apply to them
gridDayLabelScalenumber1Week/multi-week/month/rolling grids: size of the date furniture (day names, day numbers, week numbers, and the badges sharing their row), 0.8 to 2. Event pills keep tracking the module's own font size, so this makes the dates readable from across the room without costing rows per cell
sourceFilterarrayunsetCalendar source IDs this module shows (empty or unset = all sources merged). Use it to give one screen a single family member's calendar
titleFilterobjectunsetKeyword filter on event titles: { mode, terms } where mode is include (keep only matching events) or exclude (drop them). Terms are case-insensitive substrings; an empty terms list means no filter
accentColorstring"#3b82f6"Event indicator bar and today highlights
dailyShowDescriptionbooleanfalseShow the event description under the title (daily view)
agendaShowDescriptionbooleanfalseShow the event description under the title (agenda view)
eventTapDetailsbooleanfalseOn touch displays, tap an event to open a detail panel with its time, location, and description
eventTapStylestring"sheet"How the event detail opens: sheet (slides up from the bottom) or card (centered card)
showCountdownbooleanfalseDaily and agenda views: show a "in 2 hours" style countdown next to upcoming events
showProgressBarbooleanfalseDaily and agenda views: show a progress bar on events happening right now
emptyDayTextstring""Daily view: custom wording for days with no events (for example "Free day!")
agendaSeparatorsstring"none"Agenda view boundary markers: none, weeks, or weeks-and-months
agendaShowFinishedTodaybooleanfalseAgenda view keeps events that already ended today on the list (dimmed) until midnight, and an event that spans several days (a trip, a race weekend) groups under today while it's still running instead of under the day it started
showLegendstring"off"A color key naming each calendar the module is showing: off, header, or footer
showNameTagsbooleanunsetName tags: put the owning family member's initials, in their color, where the calendar dot goes. Who owns which calendar is set in Settings > Calendar > People. Calendars nobody owns keep a plain dot
legendModestringunsetWhat the color key lists: calendars (one row per calendar), people (one avatar per family member who owns a calendar with an event in view, plus Everyone for shared calendars) or groups (one row per family group as a stack of avatars, then members in no group, then Everyone)
peopleFilterobjectunsetShow only these people: family member ids and family group ids. Groups are expanded and people are mapped to their calendars when the screen renders, so adding someone to a group updates every screen that shows it. Applies together with sourceFilter
dimPastEventsbooleanfalseDaily view: fade events in today's column that have already ended. Deliberately different from the Full-Screen Calendar's same-named option, which fades whole past days and defaults on
showNowRulebooleanfalseDaily view: a thin accent rule between today's finished and upcoming events
eventRulesarrayunsetRestyle or hide individual events by what they match. See Event and day rules below
dayRulesarrayunsetTint whole days and add badges to them. See Event and day rules below

Configure sources in Settings > Calendar: see Calendar setup. Supports multiple calendars with color-coding (native colors when using Google OAuth; manual per-feed color when using iCal URLs).

Colored event style: In colored mode, timed events drop the dot and pill and render their start time plus title in the calendar's own color, the time prefix is constant-width and zero-padded (e.g. 08:05 AM) and follows the household Time format setting. All-day events render as solid calendar-color pills with white or near-black text depending on the color's brightness. Day cells list all-day events first, then timed events by start time, in both styles.

Grid themes: The multi-week and month views share one grid and one theme. banner is the original look. The three newer themes share a cleaner grid, a month heading at the top, small day numbers with a filled badge on today, a ring around today's cell, and multi-day events drawn as one connected bar, and differ in how events render: clean shows a short colored time next to a bold title, minimal drops times so full titles always fit (best at 6+ weeks or across the room), and vivid fills every event with its calendar color for maximum pop. In the month view the days before and after the month are dimmed; in the multi-week view the days already passed this week are dimmed and each new month is marked on its first day. Calendar modules start on banner; switch the theme under the View Mode picker. The rolling weeks view (viewMode: "rolling", 1–8 weeks via weeksToShow) uses the same themes; its top-left cell is always today, weekend cells are shaded under every theme (banner included), and each new month is marked on its first day.

Countdown

Counts down to one or more future events with visual progress rings.

Type countdown · Default size 380 × 360

OptionTypeDefaultDescription
eventsarray[]List of events, each with id, name, date, optional recurring ("yearly"), optional source ("custom" or "holiday"), and optional backgroundImage
showPastEventsbooleanfalseContinue showing events after they pass
stayUntilEndOfDaybooleanfalseKeep an event that has reached zero on screen until the end of that day, so a birthday or anniversary stays up all day instead of vanishing at midnight
scalenumber1Visual scale factor (0.5–5.2). View-independent: the same value renders the same size in every view
viewstring"all"Display mode: all (show all events) or next (show only the next upcoming event)
holidayCountrystringunsetISO country code to auto-populate holiday countdowns (e.g. "US")
formatstring"flip"How the numbers render: flip (animated flip cards), or one of the Clock elapsed text styles: units, unitsUpper, unitsShort, colon, words, wordsTitle
precisionstring"auto"Which units are shown: auto, days, daysHours, daysHoursMinutes, or daysHoursMinutesSeconds. auto shows days only when there is at least one, and always shows hours, minutes, and seconds.

Date

A dedicated date display module with multiple visual layouts and optional metadata (week number, day of year).

Type date · Default size 380 × 280

OptionTypeDefaultDescription
viewstring"full"Display style: full, minimal, stacked, editorial, or banner
dateFormatstring"MMMM d"Date format string (date-fns format, used in minimal view)
timezonestring""IANA timezone to show (e.g. "Asia/Tokyo"); empty = follow the display setting
showDayNamebooleantrueShow day of week name
showYearbooleanfalseShow year
showWeekNumberbooleanfalseShow week number (e.g. "Week 12")
showDayOfYearbooleanfalseShow day of year (e.g. "Day 75")
accentColorstring"#22d3ee"Accent color for day number and dividers

View details:

  • full: Large centered day number with month name and optional day name.
  • minimal: Compact single-line format with custom date formatting.
  • stacked: Vertically stacked layout with decorative divider lines.
  • editorial: Horizontal layout with large day number on left and details on right.
  • banner: Horizontal all-caps banner with elements separated by bullets.

Year Progress

Visual progress bars showing how far through the current time periods you are.

Type year-progress · Default size 400 × 300

OptionTypeDefaultDescription
showYearbooleantrueShow year progress
showMonthbooleantrueShow month progress
showWeekbooleantrueShow week progress
showDaybooleantrueShow day progress
showPercentagebooleantrueShow percentage labels
accentColorstring"#000000"Accent color for progress bars and glow effects

Multi-Month Calendar

Displays multiple months in a vertical or horizontal layout with today highlighted.

Type multi-month · Default size 400 × 700

OptionTypeDefaultDescription
viewstring"vertical"Layout direction: vertical or horizontal
monthCountnumber3Number of months to display
startDaystring"sunday"First day of week: sunday or monday
showWeekNumbersbooleanfalseShow ISO week numbers
highlightWeekendsbooleantrueDim weekend days
showAdjacentDaysbooleantrueShow days from adjacent months in empty cells
showCurrentMonthLabelbooleantrueShow the name of the current month above its grid (later months always keep theirs)
todayStylestring"filled"How today is marked: filled, square, outline, underline, text, or none
accentColorstring"#3b82f6"Color of today's marker
fitToBoxbooleantrueSize the calendar to the module instead of to the text size setting.

Weather & Environment

Weather

Unified weather module with 8 views and 9 provider options.

Set your location first

Every weather view needs a latitude and longitude. Set them once in Settings > Weather. Without a location the module shows an error rather than a forecast.

Five providers work with no API key at all: Open-Meteo, NOAA (US only), Yr.no, SMHI, and Environment Canada. Four need a free key added on the provider's own card under Settings > Weather: OpenWeatherMap, WeatherAPI, Pirate Weather, and Met Office.

Type weather · Default size 640 × 360

OptionTypeDefaultDescription
viewstring"hourly"Which view to render (see list above). One of current, hourly, daily, combined, compact, table, precipitation, alerts
iconSetstring"color"Icon style: outline or color
providerstring"global"Weather provider: global (use global setting), openweathermap, weatherapi, pirateweather, noaa, open-meteo, yr, smhi, metoffice, or envcanada
hoursToShownumber8Number of hours to display (hourly view)
showFeelsLikebooleantrueShow "feels like" temperature
daysToShownumber5Number of forecast days (daily view)
showFeaturedDaybooleantrueDaily view: show the first forecast day as a larger featured block before the remaining days
showRelativeDayLabelsbooleantrueDaily view: label the first two days as Today and Tmrw instead of weekday names
showHighLowbooleantrueShow high/low temperatures
showPrecipAmountbooleanfalseShow precipitation amount
showPrecipitationbooleantrueShow precipitation chance
showHumiditybooleanfalseShow humidity percentage
showWindbooleanfalseShow wind speed
showPressurebooleanfalseShow barometric pressure
showVisibilitybooleanfalseShow visibility distance
showDewPointbooleanfalseShow dew point temperature
hideWhenNoAlertsbooleanfalseHide the alerts view when there are no active alerts
showLocationbooleanfalseShow a place-name header above the view
locationLabelstringunsetCustom text for the location header. Empty falls back to the geocoded place name, then to the formatted coordinates
showTitlebooleantrueShow the "Forecast" / "Hourly Forecast" heading (hourly, daily, and table views)

View details:

  • current: Large current temperature with conditions, high/low, and optional stats.
  • hourly: Horizontal scrolling hourly forecast.
  • daily: Multi-day forecast with high/low temperatures.
  • combined: Current conditions with hourly and daily sections in one view.
  • compact: Minimal current temperature and icon, fits small spaces.
  • table: Tabular hourly data with columns for each stat.
  • precipitation: Minute-by-minute precipitation chart for the next 60 minutes. Requires Pirate Weather provider for minutely data.
  • alerts: Active weather alerts with severity levels. Needs a provider that publishes alerts: Pirate Weather or NOAA (US only, no API key needed). Other providers return no alerts.

Moon Phase

Current moon phase with visual representation.

Type moon-phase · Default size 300 × 350

OptionTypeDefaultDescription
showIlluminationbooleantrueShow illumination percentage
showMoonTimesbooleantrueShow moonrise/moonset times

Uses the suncalc library for calculations based on your configured latitude/longitude.

Sunrise / Sunset

Today's sunrise and sunset times with visual arc.

Type sunrise-sunset · Default size 400 × 200

OptionTypeDefaultDescription
viewstring"default"Display style: default, arc, or circle
showDayLengthbooleantrueShow total daylight hours
showGoldenHourbooleanfalseShow golden hour times
showAstroDarkbooleanfalseShow when full darkness starts and ends, and how long it lasts (always on with the sky theme)
themestring"simple"Circle-view ring coloring: simple (flat daylight/twilight/darkness segments) or sky (a gradient through the day's sun colors, with stars in the full-darkness window). The sky theme always shows the astro-dark times.

Uses the suncalc library based on your configured latitude/longitude. With showAstroDark on, the dark times always describe tonight: darkness starting this evening paired with its end tomorrow morning. On summer nights when the sky never gets fully dark, the dark rows are simply hidden. The circle view draws a 24-hour ring with noon at the top and midnight at the bottom, shading daylight, twilight, and full darkness to scale. In the circle view, the sky theme replaces those flat segments with a smooth gradient from sunrise through noon and sunset into the night, dotted with stars while full darkness lasts. Under the midnight sun the ring holds its daylight color with the sun always up; through a polar night the sky theme turns the whole ring dark with stars all around, while simple keeps its twilight shading (flat twilight when the sky never gets fully dark).

Air Quality

Air quality index and pollutant levels.

Type air-quality · Default size 350 × 250

OptionTypeDefaultDescription
showAQIbooleantrueShow air quality index
showPollutantsbooleanfalseShow individual pollutant levels (PM2.5, PM10, O3, NO2)
refreshIntervalMsnumber300000Refresh interval (5 min)

Requires an OpenWeatherMap API key (on its card under Settings > Weather) and a location set in Settings > Weather. The location is checked first, so a missing location shows an error even when the key is in place.

Rain Map

Animated precipitation radar map over an OpenStreetMap base map. Shows the past two hours of radar and the next hour of nowcast frames. Radar comes from LibreWXR, a free community server; a household running its own LibreWXR points the hub at it under Settings > Weather > Rain radar.

Type rain-map · Default size 500 × 500

OptionTypeDefaultDescription
latitudenumber0Map center latitude (falls back to global setting)
longitudenumber0Map center longitude (falls back to global setting)
zoomnumber6Map zoom level (1–12)
animationSpeedMsnumber500Delay between animation frames
extraDelayLastFrameMsnumber2000Extra pause on the last frame before looping
colorSchemenumber2Radar color scheme (0–8, the RainViewer numbering LibreWXR keeps; 2 is Universal Blue)
smoothbooleantrueSmooth radar rendering
showSnowbooleantrueShow snow on radar
opacitynumber0.7Radar overlay opacity (0–1)
showTimestampbooleantrueShow relative timestamp label
showTimelinebooleantrueShow timeline dots at the bottom
refreshIntervalMsnumber600000How often to fetch new radar data (10 min)
mapStylestring"dark"Base map style: dark or standard

News & Finance

News Headlines

Headlines from any RSS 2.0, RSS 1.0 (RDF), Atom, or JSON feed, several feeds merged into one list. The News guide walks through picking feeds, local news, topics, and filters.

Feeds are a list. Each entry is { "id", "url", "label"?, "color"?, "homeNetwork"?, "maxItems"? }. url is a real feed address or one of the shorthands local (news near the household location in Settings), topic:<keywords>, youtube:<channelId>, or reddit:<subreddit>.

Type news · Default size 540 × 420

OptionTypeDefaultDescription
viewstring"headline"Display mode: headline (one story at a time), list, ticker, compact, or cards (photo grid)
rotateIntervalMsnumber10000How often the headline view moves to the next story, and how often list and cards views turn the page when stories do not all fit (10 sec)
showTimestampbooleanfalseShow how long ago each story was published
showDescriptionbooleanfalseShow the story summary (headline, list, and cards views)
tickerSpeednumber5Seconds per story in the ticker view
accentColorstringunsetList bullet, "Just in" pill, and new-story dot colour (optional)
titlestringunsetHeader text; unset shows "News" in the display language
showTitlebooleantrueShow the built-in header (headline and list views)
showSourcebooleantrueShow the feed name next to each story
showImagesbooleantrueShow story pictures where the view has room (headline, list, cards)
descriptionLinesnumber2Lines of summary before it is cut off (1 to 4)
singleLineTitlesbooleanfalseCut headlines to one line
showCounterbooleantrue"3 of 12" in the header of the headline view, and the page count on list and cards
highlightBreakingbooleanfalseMark stories under an hour old with a "Just in" pill
showNewMarkerbooleanfalseDot stories that arrived since the display's last refresh
cardColumnsnumber2Columns in the cards view (1 to 3); rows are however many fit
tickerSeparatorstring"dot"Glyph between ticker stories: dot, pipe, or slash
feedsarrayone entryFeeds to follow, in order (up to 12). label overrides the name shown as the story source; color tints the source dot; homeNetwork lets the hub read a feed from a device on your own network (a self-hosted reader); maxItems caps stories from that feed before merging
refreshIntervalMsnumber300000How often to fetch new stories (5 min)
maxItemsnumber10Stories to show after merging every feed (3 to 24)
maxAgeHoursnumber0Hide stories older than this many hours; 0 = any age
blockedWordsstring""Comma or newline separated words; a story mentioning any of them in its headline or summary is hidden
requiredWordsstring""Comma or newline separated words; only stories mentioning one of them show
preserveOrderbooleanfalseKeep each feed's own order instead of sorting newest first
tapActionstring"qr"What a tap does on a touch display: qr (a code that opens the story on your phone), details (the summary, with a small code), or none

Stock Ticker

Real-time stock prices from Yahoo Finance.

Type stock-ticker · Default size 400 × 300

OptionTypeDefaultDescription
symbolsstring"AAPL,GOOGL,MSFT"Comma-separated stock symbols
refreshIntervalMsnumber30000Refresh interval (30 sec)
viewstring"cards"Display mode: cards, ticker, table, compact, or single. single dedicates the tile to the first symbol: ticker and company name, large price with change, and one chart filling the tile (min/max axis labels; in the shaded theme, hour marks on the day chart and day marks on the week chart, in the symbol's own exchange hours). Only that first symbol is fetched
cardScalenumber1Size multiplier for the cards, table, and compact views (0.5–3). The quickest way to make prices readable across a room. Not used by the ticker or single views
tickerSpeednumber5Scroll speed for ticker view
showSparklinebooleantrueDraw a small trend line on each card in the cards view
sparklineModestring"day"Which chart each card shows: day, week, or both (the week chart sits left of the day chart, so the pair reads chronologically)
sparklineThemestring"classic"Chart look: classic (plain line, evenly spaced) or shaded (soft backdrop and tint, day chart scaled to trading hours)
sparklineLabelsbooleanfalseCaption each chart with its range (1D for today, 5D for the past week) so the two are easy to tell apart. In the shaded theme the week chart is also ticked into its trading sessions

Each chart is colored by its own period's move (the day chart by today's change, the week chart by the week's change) in both themes; the price-change text always shows today's change. In the shaded theme the day chart's width represents that symbol's full regular trading session on its own exchange (for example 9:30 to 16:00 Eastern for US stocks), so during the session the line stops at the current time and the empty part of the chart is the remaining trading time. Outside the session, or when the session bounds are not available, the points are spread evenly across the full width. The classic theme always spreads points evenly. The single view's chart honors sparklineTheme, sparklineMode, and sparklineLabels (its captions read 1-day / 5-days); when both charts are shown they share one vertical scale.

Crypto Price

Cryptocurrency prices from CoinGecko.

Type crypto · Default size 400 × 250

OptionTypeDefaultDescription
idsstring"bitcoin,ethereum"Comma-separated CoinGecko IDs
refreshIntervalMsnumber30000Refresh interval (30 sec)
viewstring"cards"Display mode: cards, ticker, table, or compact
cardScalenumber1Size multiplier for the cards, table, and compact views (0.5–3). Not used by the ticker view
tickerSpeednumber5Scroll speed for ticker view
showSparklinebooleantrueDraw a small trend line on each card in the cards view

Sports Scores

Live and recent scores from ESPN for the leagues you turn on. College teams in the AP top 25 show their rank in front of the abbreviation.

Type sports · Default size 480 × 340

OptionTypeDefaultDescription
viewstring"scoreboard"Display mode: scoreboard, cards, list, ticker, or team (one card per favorite team)
leaguesarray["nba","nfl"]Leagues to show: nfl, ncaaf, nba, ncaam, wnba, ncaaw, mlb, nhl, mls, epl, laliga, bundesliga, seriea, ligue1, liga_mx
favoriteTeamsarray[]Teams whose games come first, as <league>:<abbreviation> (for example nfl:MIN, ncaaf:MINN). The first team gets the top spot. The team view shows one card per entry.
favoritesOnlybooleanfalseShow only games with a favorite team
refreshIntervalMsnumber60000Refresh interval (1 min)
tickerSpeednumber5Scroll speed for ticker view

Supported leagues (15): NFL, College Football, NBA, Men's College Basketball, WNBA, Women's College Basketball, MLB, NHL, MLS, Premier League (EPL), La Liga, Bundesliga, Serie A, Ligue 1, Liga MX.

Favorite teams: each entry in favoriteTeams is the league id and ESPN's team abbreviation joined by a colon, for example nfl:MIN or ncaaf:MINN. The editor's My teams search fills this in from the league's roster, so you never type an abbreviation by hand. Games with a favorite come first, in the order the teams are listed, and carry a thin bar in the team's color; favoritesOnly hides every other game. The list holds at most eight teams.

View details:

  • scoreboard: One game at a time with logos, records and the score or kickoff, rotating every 10 seconds.
  • cards: A two-column grid of compact game cards.
  • list: One line per game, league code first, for many games at once.
  • ticker: A scrolling marquee of scores; tickerSpeed sets seconds per game.
  • team: One card per favorite team showing its record, standing line, the live or next game with broadcast and venue, and the last result. Several favorites take turns every 10 seconds. A team whose league is switched off in Leagues gets no card.

Sports Standings

League standings from the ESPN standings API with team logos and colors. Supports automatic rotation through division/conference groups. A team listed in favoriteTeams (same league:abbreviation form as Sports Scores, picked with the My teams search) gets its row tinted in the team's color, and college teams in the AP top 25 show their rank after the name.

Type standings · Default size 500 × 500

OptionTypeDefaultDescription
viewstring"table"Display mode: table, compact, or conference
leaguestring"nba"League to display (see list below)
groupingstring"conference"How to group teams: division, conference, or league
favoriteTeamsarray[]Teams whose rows stand out, as <league>:<abbreviation> (for example nfl:MIN)
teamsToShownumber0Limit number of teams per group (0 = show all)
showPlayoffLinebooleantrueDraw a visual line below the last playoff spot
rotationIntervalMsnumber10000How often to rotate between groups (10 sec)
refreshIntervalMsnumber300000Data refresh interval (5 min)

Supported leagues (15): NFL, College Football, NBA, Men's College Basketball, WNBA, Women's College Basketball, MLB, NHL, MLS, Premier League (EPL), La Liga, Bundesliga, Serie A, Ligue 1, Liga MX. College leagues group by conference; the division grouping falls back to conferences for them.

View details:

  • table: Full standings table with W-L record, winning percentage, games back, streak, and more. Rotates through groups automatically.
  • compact: Condensed single-column layout showing team logo, abbreviation, and record. Rotates through groups.
  • conference: Side-by-side conference view showing two groups simultaneously with team rankings.

Knowledge & Fun

Dad Joke

Displays a random dad joke that refreshes periodically.

Type dad-joke · Default size 500 × 200

OptionTypeDefaultDescription
refreshIntervalMsnumber60000How often to fetch a new joke (1 min)
accentColorstring"#000000"Accent color for background tint and decorative elements
showDividersbooleantrueShow decorative dividers

Quote of the Day

Daily inspirational quote from ZenQuotes.

Type quote · Default size 500 × 200

OptionTypeDefaultDescription
refreshIntervalMsnumber3600000Refresh interval (1 hour)
accentColorstring"#000000"Accent color for decorative quotation mark, left border, and attribution divider

Word of the Day

Displays a vocabulary word with its part of speech and definition. Words come from a built-in list in your configured language (all seven shipped languages have their own list), and the word is picked from the date, so every display shows the same word on the same day.

Type word-of-day · Default size 450 × 200

OptionTypeDefaultDescription
accentColorstring"#000000"Accent color for underline and part-of-speech tag
showDividersbooleantrueShow decorative dividers between sections

This Day in History

Historical events that happened on today's date. Fetches from two data sources, Wikipedia "On This Day" and MuffinLabs, in parallel, deduplicates by year (preferring Wikipedia's richer text), and shuffles. Each source degrades gracefully if the other fails. Both sources return English text (the Wikipedia feed this module uses is English-only), and each contributes up to 10 events per day.

Type history · Default size 500 × 200

OptionTypeDefaultDescription
refreshIntervalMsnumber3600000Data refresh interval (1 hour)
rotationIntervalMsnumber10000How often to rotate between events (10 sec)
accentColorstring"#000000"Accent color for years-ago badge and dividers
showDividersbooleantrueShow decorative dividers
sourceMuffinLabsbooleantrueEnable MuffinLabs data source
sourceWikipediabooleantrueEnable Wikipedia "On This Day" data source
showTitlebooleantrueShow the "On This Day" header. Turning it off hides the divider under it too

Personal

To-Do List

Shows one of the family's shared lists (see Lists). Items live in data/todos.json, not on the module, so the same list can sit on any number of screens and the phone, the wall and the editor always agree.

Type todo · Default size 440 × 420

OptionTypeDefaultDescription
listIdstringunsetWhich shared list to show. Unset renders a "pick a list" placeholder. Ignored by the board view
viewstring"list"list, focus (next three in big type), progress (ring), board (every list as a column) or compact
titlestring""Heading override. Empty shows the list's own name
showTitlebooleantrueShow the heading. The done count stays either way
accentColorstring"#3b82f6"Accent for checkboxes, strikethrough and the progress ring
interactivebooleantrueRender items as tap targets so anyone at the kiosk can tick them. A tap writes to the shared list, never to the layout
completedPlacementstring"bottom"Where done items go: bottom (sink under the open ones), inline (stay put) or hidden
showDueDatesbooleantrueDue-day chips (Today, Tomorrow, Overdue, a weekday, a date) on items that carry a date
showAssigneesbooleantrueInitials, in their colours, of the people an item is for (two, then "+N"); people come from Settings > Family

When every item is done the heading shows a green tick and "All done" in every view. A list with a repeat schedule says when it starts fresh.

Sticky Note

A colored note card for freeform text.

Type sticky-note · Default size 300 × 250

OptionTypeDefaultDescription
contentstring"Write something here..."Note text content
noteColorstring"#fef08a"Background color of the note

Greeting

Displays a time-aware greeting (Good morning/afternoon/evening). When weather-aware mode is enabled and location is configured, the greeting also shows a short contextual subtitle like "Rainy day ahead" or "Storm rolling in."

Type greeting · Default size 500 × 150

OptionTypeDefaultDescription
namestring"Friend"Name to greet (e.g. "Good morning, Bryan")
accentColorstring"#000000"Accent color for the greeting text
weatherAwarebooleantrueShow a contextual weather subtitle beneath the greeting. Set to false to keep the behavior it had before the event bus. Requires latitude/longitude configured in Settings > Weather, the editor surfaces a hint in the Greeting config section if location is missing.

Todoist

Displays tasks from the Todoist API with filtering, grouping, and multiple view modes.

Type todoist · Default size 440 × 420

OptionTypeDefaultDescription
viewModestring"list"View mode: list, board, or focus
groupBystring"date"How to group tasks: none, project, priority, date, or label
sortBystring"default"Sort order: default, priority, due_date, or alphabetical
projectFilterstring""Comma-separated project names to show (empty = all)
labelFilterstring""Comma-separated label names to filter by (empty = all)
showNoDueDatebooleantrueShow tasks without a due date
showSubtasksbooleantrueShow subtasks indented under parents
showLabelsbooleantrueShow task labels
showProjectbooleantrueShow project name and color dot
showDescriptionbooleanfalseShow task description text
maxTasksnumber30Maximum number of tasks to display
refreshIntervalMsnumber60000How often to fetch tasks (1 min)
titlestring"Todoist"Module header title
showTitlebooleantrueShow the title text. The task count stays either way
allowCompletebooleanfalseShow a tappable circle on each task. Tapping marks the task complete in Todoist (optimistic, with cache invalidation so the task disappears immediately). When off, the priority bar is shown instead.

Requires a Todoist API token in settings. Markdown formatting in task content and descriptions (links, bold, italic, code, images) is stripped before rendering so kiosks don't show raw [Watch](url) syntax.

View details:

  • list: Grouped task list with priority bars, due date badges, project/label metadata, and subtask nesting.
  • board: Kanban-style columns (up to 3) grouped by the selected groupBy option.
  • focus: Shows only today's and overdue tasks with a count of remaining items.

Garbage Day

Trash and recycling collection schedule. Highlights when collection day is approaching based on your chosen trigger mode.

Type garbage-day · Default size 350 × 320

OptionTypeDefaultDescription
trashDaynumber1Trash collection day (0=Sun through 6=Sat, -1=disabled)
trashFrequencystring"weekly"Collection frequency: weekly or biweekly
trashStartDatestring""Anchor date for biweekly calculation (ISO date)
trashColorstring"#6ee7b7"Trash icon color
recyclingDaynumber1Recycling collection day (same format as trashDay)
recyclingFrequencystring"weekly"Recycling frequency: weekly or biweekly
recyclingStartDatestring""Anchor date for biweekly recycling
recyclingColorstring"#93c5fd"Recycling icon color
customDaynumber-1Custom collection day (-1 = disabled)
customFrequencystring"weekly"Custom frequency: weekly or biweekly
customStartDatestring""Anchor date for biweekly custom collection
customColorstring"#fbbf24"Custom icon color
customLabelstring"Yard Waste"Label for the custom collection type
highlightModestring"day-before"When to highlight: day-of or day-before
showTitlebooleantrueShow the built-in "Collection Schedule" header

Supports up to 3 collection types: trash, recycling, and a customizable third type (e.g. yard waste, compost). Each type can run on its own weekly or biweekly schedule.

Affirmations

Displays rotating positive affirmations with multiple visual styles. Time-aware selection adjusts messages based on time of day, day of week, and season. Weather-aware scoring quietly boosts entries that match the current conditions without hiding anything, so a rainy morning is more likely to surface a cozy gratitude entry and a snow day is more likely to surface a mindfulness entry tagged snow. The day-of-week and season rules are stricter than the weather one: an entry tagged for a specific day or season is held back entirely outside it, rather than just ranked lower.

Type affirmations · Default size 500 × 200

OptionTypeDefaultDescription
viewstring"elegant"Display style: elegant, card, minimal, or typewriter
categoriesarray3 entriesCategories to include: affirmations, compliments, motivational, gratitude, mindfulness
rotationIntervalMsnumber15000How often to rotate to the next affirmation (15 sec)
showCategoryLabelbooleanfalseShow the category label below the affirmation
timeAwarebooleantrueSelect affirmations based on time of day, day of week, and season
weatherAwarebooleantrueGive entries tagged with a matching weather condition a +2 score boost. Non-matching entries are never hidden. Only takes effect while Time-aware is on, since the weather boost is part of the same scoring pass. Requires latitude/longitude configured in Settings > Weather, the editor surfaces a hint in the Affirmations config section if location is missing.
customEntriesarray[]Custom affirmations, each with id, text, and optional attribution
accentColorstring"#a78bfa"Accent color for card/typewriter views

View details:

  • elegant: Large centered text with a subtle gradient backdrop.
  • card: Rounded card with accent-colored left border.
  • minimal: Simple text with no decoration.
  • typewriter: Typewriter-style animation that types out each affirmation.

Meal Planner

A meal planning module for organizing daily meals across configurable slots (breakfast, lunch, dinner, snack). Time-aware slot detection highlights the current or next meal.

Type meal-planner · Default size 500 × 600

OptionTypeDefaultDescription
viewstring"week"Display style: week, today, next-meal, compact, or list
showEmojibooleantrueShow meal emoji
showPrepTimebooleantrueShow prep time in minutes
showTagsbooleantrueShow meal tags
accentColorstring"#f59e0b"Accent color for highlights
tapRecipeActionstring"off"What tapping a meal with a saved recipe link does: off, qr (fullscreen QR code overlay), or iframe (embed the recipe page)
showTitlebooleantrueShow the "Today's Meals" label in the today view

Recipe links: Meals saved with a recipe link (added from /remote > Meals) can open that recipe right on the display. With qr, tapping the meal shows a fullscreen QR code you scan with your phone; with iframe, the recipe page opens in an overlay on the display itself (some recipe sites block embedding, the QR option always works). In the editor preview, tapping opens the recipe in a new browser tab instead.

Enabled slots, week start day, default slot times, and 12/24h formatting are household-level settings edited once under /remote > Meals > Settings, every meal-planner module across every display picks them up from data/meals.json automatically. The time format defaults to the household Time format setting (Settings → Defaults → Location & language); pick an explicit 12- or 24-hour option in meal settings only if meals should differ from it. Meal data (saved meals and weekly plan) lives in the same file and is shared across the standard widget, fullscreen display, editor, and remote via /api/meals/data. The plan uses ISO date strings (e.g. "2026-04-04") to support multi-week planning with week navigation. Old day-of-week configs are auto-migrated. Entries older than 12 weeks are pruned automatically.

View details:

  • week: Grid showing all 7 days and meal slots at a glance with today highlighted.
  • today: Vertical stack of slot cards for today with active slot highlighted.
  • next-meal: Large display of the next upcoming meal with context label (Now/Coming Up/Tomorrow).
  • compact: Two-column layout showing Today and Tomorrow side-by-side.
  • list: Full week listed vertically with day headers, showing only days with meals.

Chore Chart

A chore tracking module for families or housemates. Assign chores to members with tickets, streaks, rotation schedules, and multiple visual layouts. Includes a rewards system where members earn tickets from completed chores and can redeem them for parent-defined rewards (managed via the remote's Chores tab).

Type chore-chart · Default size 1000 × 560

OptionTypeDefaultDescription
viewstring"board"Display style: board, star-chart, today, progress, compact, reward-history, or rewards-store
weekStartDaystring"monday"First day of week: sunday or monday
showPointsbooleantrueShow ticket values for chores
showStreaksbooleantrueShow completion streaks
showTimeOfDaybooleantrueShow time-of-day labels (morning, afternoon, evening)
allowDisplayCompletebooleantrueAllow marking chores complete from the display view
accentColorstring"#f59e0b"Accent color for highlights
showTitlebooleantrueShow the built-in view title ("Family Chores", "Star Chart", and so on)
historyLimitnumber5Maximum number of redemptions shown in Reward History. Omitted = 5.
storeLayoutstring"list"Rewards Store layout: list, tiles, or price-list. Omitted = list.

Members and chores are shared household data, not module options. Members live in data/family.json and chores in data/chores.json. The family roster is available under Settings > Family even without a chore chart. Both are also edited from the editor's Edit chore chart button or from /remote > Chores, so every chore module on every display shows the same people and the same list. Each member has an id, name, emoji, and color. Each chore has an id, name, emoji, points, frequency (daily, weekly, biweekly, or once), daysOfWeek, timeOfDay, specificDate (YYYY-MM-DD, required when frequency is once), assigneeIds, an optional assigneeGroupIds, rotation, and, when rotation is schedule, a schedule map of member ID to days-of-week plus an optional groupSchedule map of group ID to days-of-week.

View details:

  • board: Kanban-style board grouping chores by status or member.
  • star-chart: Kid-friendly star chart showing earned tickets per member.
  • today: Today's chores only, grouped by time of day.
  • progress: Progress bars showing completion rates per member.
  • compact: Condensed view for small module sizes.
  • reward-history: The latest rewards the family has redeemed, newest first: who, what, how many tickets, and how long ago. historyLimit sets how many to list (1 to 50). The type shrinks so the list fits the card, down to a readable floor; past that the card says how many more are below.
  • rewards-store: Spend tickets from the card itself. storeLayout picks how it looks: list (pick a person, then one reward per row with a Redeem button or how many more tickets to go), tiles (the same, as a grid of tiles), or price-list (every reward with how many people can afford it; tapping one asks who it is for). Redeeming always asks first. A wide, short card moves the person picker to the side. With allowDisplayComplete off the view is a price list with nothing to tap. The History button in the title opens the reward history in place.

Rotation modes:

A chore goes to the people in assigneeIds plus everyone in the family groups named by assigneeGroupIds, each person counted once. Groups are looked up every time the chore is resolved and are never copied into assigneeIds, so somebody added to a group later gets its chores without the chore being edited. People named directly come first in their saved order, then each group's members.

Each chore has a rotation field that controls how that combined list is resolved each day.

  • fixed: Everyone on the list is responsible for the chore every time it appears. Use this for chores a single person always owns.
  • rotate-daily: Cycles through the list one day at a time, so Alice handles it today, Bob handles it tomorrow, and so on.
  • rotate-weekly: Same as daily rotation but the handoff happens on Monday, whatever day the chart's week starts on.
  • schedule: Per-day assignment via a schedule map of memberId → number[] (days-of-week, 0 = Sunday through 6 = Saturday). Lets you say "Alice on Mon/Wed, Bob on Tue/Thu, everyone on Fri–Sun" without creating separate chores. The editor and the remote both render a weekly grid UI for editing the schedule, and any day not covered by the schedule simply has no one assigned. A family group can have a row of its own: groupSchedule is the same kind of map keyed by group ID, and everyone in the group has the chore on those days, including somebody who joins the group later. Every group with a row is also listed in assigneeGroupIds. A person who has their own row and is also in a scheduled group has the chore on either set of days. A chore in schedule mode also shows a small (schedule) label in the board when resolved to a single assignee, so you can tell it apart from a fixed one-person chore at a glance.

Chore ticket values can be any non-negative integer, 0 is allowed and is useful for tracking routines that do not earn rewards.

School Timetable

One week card per child: the school week as a grid, the day that is on now widened and lit, and the rest of the week beside it. Nothing about a person is stored here, a card is drawn from the family roster in data/family.json and the week in data/timetables.json, joined by member ID. See School timetable for the parent-facing walkthrough.

Type timetable · Default size 1000 × 880

OptionTypeDefaultDescription
memberIdsarray[]Whose school week to show. Cards follow the order Settings > Family lists people in, and anyone without a timetable yet is left out
viewstring"week"week shows each person's whole week. day puts everyone's next school day on one clock, with when each of them starts and finishes and what goes in the bag. Omitted = week
tomorrowFromstring"16:00"Day view only. Before this time of day the card shows today; from it on, the next school day. 'HH:MM' on a 24 hour clock. Omitted = 16:00
showNowLinebooleantrueDay view only. A line across the clock at the current time while the card shows today. Omitted = shown
layoutstring"side-by-side"Week cards side by side across the screen, or stacked one above the other. The module keeps the arrangement you pick and never swaps it to fit the box. One of side-by-side, stacked
detailstring"some"How much each lesson shows: less keeps short subject codes, some adds full names and rooms, more adds start and end times, the A or B week letter and a packing line
showStartTimesbooleantrueShow the time each period starts beside its number. Omitted = shown
nextWeekFromFridaybooleantrueOnce the last lesson of the school week is over, show next week instead of an empty weekend. Omitted = on

Timetables are shared household data, not module options. config.memberIds only says whose cards this module draws; the weeks themselves, the schools they hang off and the subject list they paint from live in data/timetables.json and are edited in the timetables window (Edit timetables in the module's settings panel). Every timetable module on every display therefore shows the same weeks, and a member ID with no timetable is skipped rather than drawn empty.

A school owns the bell schedule (numbered periods and named breaks in HH:MM), the optional after-school care times, the A/B week cycle, whose holidays it follows and its own dated exceptions, so siblings at one school are typed in once. Subjects are shared by every timetable: one has a short code for narrow cells, a full name, a colour, an icon name and an optional bring note. A household that has never saved gets the default subject catalogue for its language to paint with; nothing is written until the first save.

Detail levels:

  • less: short subject codes everywhere, full names in the focus column only, no rooms. Meant for three or more cards side by side.
  • some: full subject names in every column, the room on focus-column lessons, and the going-home time under the last lesson of the focus day.
  • more: rooms on every lesson, a late-start line, the week letter on lessons that differ between A and B (with a footer note naming them), an after-school care row, and a footer line collecting what to pack that day.

The period gutter carries start times while showStartTimes is on, as a start–end range at the more level and the start alone below it.

layout is never chosen for you. A module never rearranges itself by box aspect, so five cards in a wide box stay side by side and narrow themselves instead. Within that, the card derives its own afternoon fold, focus-column width and narrow-cell rules from its measured box.

Which day is lit: today, when school is open and the week is not over. Once the last lesson of the school week has finished, the card turns to next week unless nextWeekFromFriday is false. At the weekend it shows next week with Monday to the front. A day closed by a school holiday, a public holiday or one of the school's own special days is marked closed, and a holiday running right now sends the card straight to the week school starts again.

Holidays belong to the school, not to the module. TimetableSchool.holidayRegion holds an OpenHolidays region code such as DE-NW, or a bare country code such as LU for the countries that publish one set of dates and no regions. It sits on the school because a school is in a place: one setting shared by every card on a wall can only ever be right about one of a household's schools. The module dedupes the regions of the schools it is drawing, asks GET /api/timetables/holidays?region=A,B about all of them in one request, and closes each card's days from its own school's answer. A wall where no school names a region makes no holiday request at all, and with holidayRegion unset a card loses the closed days and the back-to-school line and nothing else.

The control is SchoolHolidaysEditor, in the timetables window under Schools & times, between the A/B week control and specialDays. It resolves the country from settings.calendar.holidayCountry first, then from the saved location through /api/geocode, then from the region part of GlobalSettings.locale, and asks the route what that country has. Whether a country has subdivisions and whether it has school holiday dates are read as two independent answers, which is what gives the row its six states:

  • list: subdivisions with school holiday dates behind them, offered as a <select>. A country with dates but no subdivisions lands here too, with its own code as the single option.
  • public-only: subdivisions but hasSchoolHolidays false. The same <select>, with a sentence saying only public holidays close a day.
  • no-holidays: neither subdivisions nor dates. No control at all, and a sentence pointing at Days that are different, because there is no code anybody could type that would ever answer. A region saved earlier brings the <select> back for the one job of setting it to None.
  • failed: the lookup did not answer. A free-text box for the code, committed on blur.
  • no-country: nothing resolved to ask about. The same box, with a sentence naming Settings > Calendar.
  • resolving: the same box, disabled and silent, since a message replaced half a second later reads as a fault.

The word the sentences use for a subdivision comes from regionCategory on the country answer and is localized ("Bundesland", "comunidad autónoma"), falling back to a plain "Region". Coverage is live data, so any list of countries is only as of its date: as this is written, Germany, France and the Netherlands have school holiday dates, Spain has subdivisions and no dates, and the United States, Denmark and Brazil have neither. US school closures are set district by district with no national source, so that one is not a gap an upstream fix will close. Answers are cached in data/school-holidays.json, and a failed lookup falls back to the saved copy so an offline display keeps showing the right thing.

A and B weeks are a property of the school (weekCycle), read off the ISO week number: odd weeks take the letter you pick, even weeks the other. A person's weeks.B exists only when their two weeks really differ. Dated exceptions a single school knows about (a carnival Monday off, a morning ending after period 3) are its specialDays.

Importing reads a Google Sheet: POST /api/timetables/import/check previews it without saving anything, and applying the import is an ordinary save of the whole document. The server builds every URL it fetches from the sheet ID in the pasted link and addresses a tab by gid, never by name. Days go across the top, one row per lesson, times down the left; rows named as a break become breaks and Math / A107 carries the room. A tab is matched to a family member by name, on the whole name or at least the first name turning up among the tab's words, and two people matching equally well suggests nobody rather than guessing. A code no subject matches leaves that period empty rather than guessing at one. A sample sheet is served at /samples/timetable-example.csv.

Importing a file reaches the same screen through POST /api/timetables/import/file, which reads CSV text instead of fetching anything. The browser reads the picked file and posts its text, so the file itself never leaves the machine and nothing is written anywhere; the reading is server-side because it needs the household's subject list and the family roster, and both live there. readTimetableFiles matches a file to a person by the same name rule, applied to the filename with its extension dropped, so Taylor.csv is Taylor's week, and the filename stands in for gid since there is no tab. One post carries at most sixteen files and 2 MB of text. A file import records no source: there is no link to go back to, so there is nothing to sync against, and a file replacing a week that used to follow a sheet takes that week off the sheet rather than leaving a link that no longer describes it.

Keeping a week in sync hangs off the source a sheet import records on the timetable: the link, when it was read, and the bookkeeping a re-read needs. TimetableSource carries sync (follow this sheet, re-reading it hourly), tab (the tab the import took, so a re-read goes to the same one rather than guessing), codes (the subject the household said each of the sheet's own codes means, saved folded so a re-read finds it however the sheet spells it that day), lastCheckedAt (when the sheet was last looked at, whatever the answer) and lastError (why the last look failed, as one of the import message keys, absent when it worked). There is no scheduler to hang the hourly check on, deliberately: the app is a single node server.js process. The check rides the read the walls already make instead, so timetableRead starts it from the display-authed GET /api/timetables and does not wait for it, the answer that route serves is always what is on disk, and a new week arrives on a later poll. A timetable is due when sync is on and lastCheckedAt is at least an hour old (SYNC_INTERVAL_MS); one round runs at a time for the whole process however many walls are polling, with a five-minute stall guard so a hung fetch cannot wedge the check off for the life of the process. POST /api/timetables/sync with a memberId is the forced check the timetables window offers for one person: it skips both the due test and that guard, and it waits for the answer, because somebody pressed it to find out. A household with no wall up and no editor open polls nothing and so checks nothing.

Three rules govern the write-back. A failed check never replaces a week: only lastCheckedAt and lastError are written and the saved week stands, and a sheet that answers but holds no readable week counts as a failure rather than as an empty week. A hand edit takes the week off the sheet: stopFollowingEditedWeek compares the person's weeks either side of every edit and clears sync, rather than asking the component that made the edit, so a new way of editing a week cannot forget the rule; the window names whose week it let off, and the switch puts it back. Only weeks.A is replaced, because that is all an import writes, so a B week built by hand is never the sheet's to touch. The write-back also checks that the saved source.url is still the one the answer came from, so a link corrected while a fetch was in the air does not have the old sheet's week written onto it.

The store caps a household at 16 schools, 16 slots per school, 64 subjects, 64 timetables and 64 special days per school, and saves are revision-checked: a save that started from an older copy is refused with the saved document attached.


Media & Display

Text

Rich text block with multiple display modes, effects, and styling options.

Type text · Default size 400 × 150

OptionTypeDefaultDescription
contentstring"Hello, World!"Text content (supports markdown when enabled)
alignmentstring"center"Text alignment: left, center, or right
orientationstring"horizontal"Text direction: horizontal, vertical, or sideways
verticalAlignstring"center"Vertical alignment: top, center, or bottom
markdownbooleanfalseEnable markdown rendering
autoFitbooleanfalseAuto-fit text size to fill the container
effectstring"none"Text effect: none, typewriter, fade-in, gradient-sweep, glow, outline, shadow, 3d, neon, wave, bounce, shake, or color-cycle
rotationEnabledbooleanfalseRotate through content split by separator
rotationIntervalMsnumber5000Rotation interval in milliseconds
rotationSeparatorstring"---"Separator string for splitting content into rotation items
gradientEnabledbooleanfalseEnable gradient text coloring
gradientFromstring"#a78bfa"Gradient start color
gradientTostring"#22d3ee"Gradient end color
gradientAnglenumber90Gradient angle in degrees
textTransformstring"none"Text transform: none, uppercase, lowercase, or capitalize
letterSpacingnumber0Letter spacing in pixels
fontFamilystringunsetFont registry id overriding the module's Style font (see Module Styling for the list). Unset = use the Style font
italicbooleanfalseItalicize the text
lineHeightnumber1.2Line height as a multiple of the font size
wordSpacingnumber0Word spacing in pixels
iconstring""Icon prefix (emoji or short text shown before content)
templateVariablesbooleanfalseEnable dynamic variables like {{time}} and {{date}} (see below)
marqueebooleanfalseEnable marquee (scrolling) text
marqueeSpeednumber30Seconds for one full scroll pass (5–120). Higher is slower
marqueeDirectionstring"left"Marquee direction: left, right, up, or down
outlineWidthnumber2Stroke width in pixels (outline effect)
outlineColorstring"#000000"Stroke color (outline effect)
shadowOffsetXnumber2Horizontal shadow offset in pixels (shadow effect)
shadowOffsetYnumber2Vertical shadow offset in pixels (shadow effect)
shadowBlurnumber4Shadow blur radius in pixels (shadow effect)
shadowColorstring"rgba(0,0,0,0.5)"Shadow color (shadow effect)
textDecorationstring"none"Line decoration: none, underline, overline, or line-through
textDecorationColorstring"#ffffff"Color of that line
textDecorationThicknessnumber2Thickness of that line in pixels
animationSpeednumber2Seconds per cycle for the animated effects
colorCyclePalettearray6 preset colorsColors the color-cycle effect cycles through
revealOnRotationstring"none"How each new item appears: none, fade, slide-up, slide-down, or zoom. Only used while rotation is on
maxWidthnumber0Maximum text width in pixels (0 = no limit)
wrapModestring"normal"Line-wrapping style: normal, nowrap, balance (even line lengths), or pretty (avoids lonely last words)
dropCapbooleanfalseEnlarge the first letter as a drop cap
dropCapColorstringunsetDrop cap color (falls back to accentColor, then the text color)
textBackgroundstringunsetColor drawn directly behind the glyphs, separate from the module's own background
textBackgroundPaddingnumber4Padding around that background in pixels
textBackgroundRadiusnumber4Corner rounding of that background in pixels
showDividersbooleanfalseShow decorative divider lines above and below the text
accentColorstring"#ffffff"Color for the dividers and the typewriter cursor

Text effects:

  • typewriter: Types out the text character by character
  • fade-in: Fades the text in smoothly
  • gradient-sweep: Animated gradient sweep across the text
  • glow: Pulsing glow effect
  • outline: Hollow, stroked letters
  • shadow: Offset drop shadow behind the letters
  • 3d: Layered letters for a raised, extruded look
  • neon: Neon-tube style glow with a bright core
  • wave: Letters ripple up and down one after another
  • bounce: Letters bounce in sequence
  • shake: Letters jitter in place
  • color-cycle: Letters cycle through colorCyclePalette

Template variables: When enabled, seven placeholders are replaced with live data: {{time}} (24-hour), {{time12}} (12-hour), {{date}}, {{day}} (weekday name), {{month}}, {{year}}, and {{greeting}}. Anything else stays on screen exactly as typed, so watch the spelling: it is {{day}}, not {{dayOfWeek}}. The greeting words are currently English only.

Shared-state tokens: Single-brace {<key>} (separate from the double-brace template variables above) inserts a live value published by an add-on, e.g. {plugin:ha:sensor.temp}. Add a filter after a | to format it: |round:1 rounds a numeric value to a set number of decimal places, and |default:TEXT supplies placeholder text for a key that hasn't published a value yet, e.g. {plugin:ha:sensor.temp|round:1|default:n/a}. Unknown keys render as an en dash with no filter.

Content rotation: Split content by a separator (default ---) and rotate through the chunks at a set interval, useful for rotating quotes, tips, or announcements.

Image

Displays a static image.

Type image · Default size 540 × 360

OptionTypeDefaultDescription
srcstring""Image URL or path
objectFitstring"cover"How the image fills the container: cover, contain, or fill
altstring""Alt text

Video

Plays a video clip, a file from your media library, a direct video URL, or a YouTube link. In the editor the module shows a still frame with a play badge; the video only plays on the actual display.

Type video · Default size 540 × 360

OptionTypeDefaultDescription
sourcestring"file"Where the video comes from: file (media library) or url (direct link or YouTube)
filestring""Path to a video in the media library (file source)
urlstring""Direct link to an MP4/WebM video, or any YouTube link (url source)
objectFitstring"cover"How the video fills the container: cover, contain, or fill
mutedbooleantrueKeep the video silent. Turning sound on also needs the display's autoplay setting (see below)
loopbooleantrueStart the video over when it ends
maxDurationMsnumberunsetStop playing after this many milliseconds (0 or unset = keep playing)

Best format for Raspberry Pi

MP4 videos with H.264 encoding play smoothly on Raspberry Pi hardware. iPhone recordings (.mov files with HEVC) may not play on a Pi 4, if a clip shows a black box, convert it to MP4 (H.264) first. If a video fails to load or stalls, playback stops cleanly instead of freezing the screen, and in a photo slideshow the show advances to the next slide.

Sound: Videos are silent by default. To play sound, turn on the module's sound toggle. Sound also needs a setting on the display itself, which every install and upgrade turns on automatically. If sound stays off on an older Pi, re-run the upgrade.

YouTube links: Paste any YouTube link (youtube.com/watch, youtu.be, or a Short) into the URL field and the module plays it with YouTube's own player, autoplaying, without on-screen controls, using the privacy-friendly no-cookie player. The sound and repeat toggles work; the time limit doesn't apply (YouTube controls its own playback). Needs internet access on the display, and the video must allow embedding.

Photo Slideshow

Rotates through images from a local directory, an Immich photo library, a OneDrive folder, or an iCloud shared album. Can mix in videos from the same source, videos play muted, advance to the next slide when they finish, and use a hard cut instead of a crossfade. Google Photos works too, as an import: the Import from Google Photos button under the folder picker downloads photos you choose into your library, see Google Photos.

Type photo-slideshow · Default size 500 × 400

OptionTypeDefaultDescription
directorystring""Directory name inside public/backgrounds/
intervalMsnumber30000Time between transitions (30 sec)
transitionstring"fade"Transition effect: fade or none
objectFitstring"cover"Image fit mode. One of cover, contain, fill
refreshIntervalMsnumber600000How often to re-scan the directory for new images (10 min)
sourcestring"local"Photo source: local, immich (requires keys in Settings > API keys), onedrive (a one-time Microsoft sign-in), or icloud (a public shared album, no keys needed)
immichAlbumIdstringunsetFilter to a specific Immich album
immichPersonIdstringunsetFilter to a recognized person (face) in Immich
immichFavoritesOnlybooleanfalseOnly show photos marked as favorites in Immich
immichCountnumber50Number of photos to load per refresh (10–200)
icloudAlbumUrlstringunsetiCloud shared album link (icloud.com/sharedalbum/#TOKEN) or bare token (iCloud source)
onedriveFolderIdstringunsetOneDrive folder to pull photos from (OneDrive source)
onedriveFolderNamestringunsetFolder name as shown in the editor, display only, the ID above is authoritative
onedriveCountnumber50Number of photos to load per refresh (10–200)
mediaTypesstring"photos"What to show: photos, videos, or both
maxVideoDurationMsnumber60000Longest a video slide can play before moving on (60 sec)

When using Immich as the source, the editor shows a connection status indicator, album and person dropdowns, a favorites toggle, a photo count slider, and a live preview strip of 4 photos matching the current filters. Album and person filters are mutually exclusive.

When using iCloud as the source, paste a public shared album link from the Photos app (Share > Copy iCloud Link on a shared album). No Apple account or API key is needed, the display loads photos straight from Apple's servers. The album must have a public website link enabled.

When using OneDrive as the source, the module signs in to your Microsoft account once with a short code, and then you pick a folder. That folder's photos feed the slideshow, subfolders included. The full walkthrough is in OneDrive photos. Photos shuffle on every refresh; very large folders use a random sample of 1,000 photos.

Mixing in videos: Set Show to Photos + videos (or Videos only) to include video clips. Photos advance on the slide interval; videos play to the end (or the video time limit) and then advance. Videos in slideshows are always silent. Immich mixed albums work out of the box; local videos are any MP4/WebM/MOV files in the same backgrounds folder.

QR Code

Generates a QR code from any text, URL, or WiFi network credentials.

Type qr-code · Default size 300 × 350

OptionTypeDefaultDescription
modestring"custom"QR code mode: custom (arbitrary data) or wifi (WiFi network)
datastring""Content to encode (custom mode)
labelstring""Label text below the code (custom mode)
ssidstring""WiFi network name (wifi mode)
passwordstring""WiFi password (wifi mode)
authTypestring"WPA"WiFi authentication type: WPA, WEP, or nopass (wifi mode)
hiddenNetworkbooleanfalseWhether the WiFi network is hidden (wifi mode)
showPasswordbooleantrueShow the password below the QR code (wifi mode)
showNetworkNamebooleantrueShow the network name below the QR code (wifi mode)
fgColorstring"#ffffff"Foreground color
bgColorstring"transparent"Background color

Web Embed

Embeds any web page or dashboard. Acts as a universal adapter for Home Assistant, Grafana, Google Sheets, Notion, and any embeddable web content.

Type iframe · Default size 540 × 360

OptionTypeDefaultDescription
urlstring""URL of the page to embed
refreshIntervalMsnumber0Auto-refresh interval in ms (0 = off)
scrollablebooleanfalseAllow scrolling within the embedded page
sandboxEnabledbooleanfalseApply sandbox restrictions to the iframe
sandboxstring"allow-scripts allow-forms allow-popups"Sandbox permission tokens (when enabled)
titlestring""Accessibility title for the iframe

About the sandbox list: what you type is checked before it is applied. Only the 13 standard sandbox tokens are recognized and anything else is ignored. allow-same-origin is also dropped whenever allow-scripts is set, because that pair lets an embedded page step outside its own sandbox, so if a self-hosted dashboard needs same-origin access, turn the sandbox off entirely rather than combining the two. Only http and https addresses can be embedded; anything else shows an error in place of the page.

Note: Some websites (e.g. YouTube, Yahoo Finance, Twitter) set frame-ancestors or X-Frame-Options headers that prevent embedding. Self-hosted services, published Google Docs/Sheets, and sites that explicitly support embedding will work.

Embedding video pages: Pages that host a video player (a YouTube embed URL, a self-hosted stream page) can be shown through this module too. If the player doesn't start with sandbox enabled, the default sandbox permissions (allow-scripts allow-forms allow-popups) may need adjusting for that player, or turn the sandbox off. For plain video files, the dedicated Video module is simpler.

Icon

A single Font Awesome 7 glyph rendered at any size with color, rotation, flip, and optional animation. Useful as a visual accent or status badge alongside other modules. Picker covers the full Free Font Awesome set (solid, regular, brands).

Type icon · Default size 240 × 240

OptionTypeDefaultDescription
iconNamestring"star"Icon name without the fa- prefix (e.g. "house", "cloud-sun", "github"). A full class string with spaces is used verbatim and ignores style
stylestring"solid"Free Font Awesome style. solid covers most icons; brands is required for logos like GitHub or Slack. One of solid, regular, brands
colorstring"#fbbf24"Icon glyph color (CSS color)
iconBackgroundstring"transparent"Background tint behind the glyph, separate from the module wrapper background
rotationnumber0Rotate the icon in 90° increments. One of 0, 90, 180, 270
flipstring"none"Mirror the icon. One of none, horizontal, vertical, both
animationstring"none"One of none, spin, spin-pulse, spin-reverse, beat, fade, beat-fade, bounce, shake, flip
animationDurationnumber2Animation cycle length in seconds (Font Awesome --fa-animation-duration)
scalenumber0.7Glyph size as a fraction of the smaller container dimension (cqmin). Ignored when autoFit is true
autoFitbooleantrueWhen true, locks scale to 0.85 so the glyph has a comfortable margin on all sides

Note: style: 'regular' only renders icons that ship in the regular outline set. If a chosen icon is not in the regular set the codepoint falls back to text, keep style: 'solid' unless you've confirmed the icon ships in fa-regular-400.

Shape & Divider

Decorative shapes and dividers for layout polish, the visual equivalent of a horizontal rule, a callout frame, or a star sticker. The view field switches between 15 distinct renderers; most options apply only to a subset of views (line variants vs. geometric vs. atmospheric vs. frame).

Type shape · Default size 400 × 80

OptionTypeDefaultDescription
viewstring"divider"Which shape to render (see list above). One of divider, double-line, wave, zigzag, dotted-row, rectangle, circle, triangle, polygon, star, arrow, glow, gradient, grid, frame
fillModestring"solid"Use a flat color or a linear gradient between gradientFrom and gradientTo. One of solid, gradient
colorstring"#ffffff"Solid fill color
gradientFromstring"#a78bfa"Gradient start color (used when fillMode = "gradient")
gradientTostring"#22d3ee"Gradient end color
gradientAnglenumber90Gradient angle in degrees
orientationstring"horizontal"Direction for line views (divider, double-line, wave, zigzag, dotted-row). One of horizontal, vertical, diagonal
thicknessnumber2Line thickness in px (line views)
lineStylestring"solid"Stroke pattern for the divider line. One of solid, dashed, dotted
endStylestring"fade"Edge treatment: flat ends, fade-to-transparent, or rounded caps. One of flat, fade, rounded
waveAmplitudenumber18Wave/zigzag amplitude as % of viewBox height (0–50)
waveFrequencynumber4Number of full wave/zigzag cycles across the width
dotCountnumber5Number of dots in the dotted-row view
dotSizenumber4Dot radius in px for dotted-row
doubleLineGapnumber6Pixel gap between the two parallel lines in double-line view
outlinebooleanfalseRender geometric shapes as outlines instead of filled
strokeWidthnumber2Outline stroke width in px
cornerRadiusnumber12Corner radius in px for rectangle
sidesnumber6Polygon side count (3–12)
starPointsnumber5Star point count (3–12)
starInnerRationumber0.4Star inner-to-outer radius ratio (0.2–0.8). Lower = pointier
rotationnumber0Rotation in degrees applied to geometric shapes
arrowDirectionstring"right"Arrow head direction. One of up, right, down, left
arrowHeadRationumber0.35Arrow head length as ratio of total length (0.1–0.6)
softnessnumber0.55Glow gradient falloff (0 = hard edge, 1 = soft edge)
intensitynumber0.55Glow center max alpha (0–1)
gridPatternstring"dots"Pattern used by the grid view. One of dots, lines, cross
gridSpacingnumber24Grid spacing in px
gridDotSizenumber2Grid dot/line thickness in px
frameStylestring"rectangle"Frame border style. One of rectangle, brackets
bracketLengthnumber25Bracket length as % of side length (5–50) when frameStyle = "brackets"

Sizing: Default size is 400×80, which gives a comfortable touch/grab target on the editor canvas. The visible glyph (e.g. a 2-px divider line) renders inside that box, the wrapper provides hit area, the line stays thin.

Display Control

Touch-friendly on-screen controls for putting a display to sleep or waking it, advancing screens, and adjusting brightness. Dispatches the same commands used by /remote: useful for bedside or hallway touchscreens where you want a physical control surface without pulling up a phone. Every button carries a word next to its icon (Previous screen, Next screen, Sleep with "hold for 1 second", Wake, Brightness). The nav layout is the pared-back one: only Previous and Next, filling the whole widget.

Type display-control · Default size 440 × 320

OptionTypeDefaultDescription
layoutstring"panel"Control layout, bar is a single row, pad a grid of large buttons with brightness on tap, panel a grid with the brightness slider always visible, nav just two big Previous and Next buttons
defaultTargetstring"self"Which display the buttons control. self resolves to the display the module is rendered on
allowRetargetingbooleanfalseShow a "Controls" dropdown of display names (with "All displays" last) so people can retarget on the wall (hidden in single-display mode)
compactbooleanfalseIcons only, no words (the buttons keep their spoken labels)

Behavior: The nav layout puts its two buttons side by side, and stacks them with up and down arrows when the widget is much taller than it is wide. Sleep requires a 1-second hold to confirm; a shorter tap flashes "Keep holding to sleep" over the button. Prev/next buttons are debounced at 200ms to collapse rapid taps. The brightness slider starts at the brightness the target display last reported (a dash until it has reported, or when "All displays" disagree) and commits on release so dragging doesn't spam the hub.

defaultTarget is resolved when the module mounts. A display id that doesn't match anything in the registry silently falls back to self: there's no error, so a typo here looks like the buttons are controlling the wrong screen rather than a broken setting.


Travel

Traffic / Commute

Shows estimated travel times for configured routes.

Type traffic · Default size 450 × 300

OptionTypeDefaultDescription
routesarray[]Routes, each with label, origin, and destination
refreshIntervalMsnumber300000Refresh interval (5 min)
showTitlebooleantrueShow the built-in "Traffic" header

Supports Google Routes API or TomTom as providers. Origins and destinations are address strings.

Requires an API key

Add either a Google Maps key or a TomTom key under Settings > API keys. Google is used when both are present.

Without a key the module still shows travel times, but they are randomly generated placeholders rather than real ones. The response is marked mock: true if you ever need to confirm which you are looking at.

With TomTom, each origin and destination address is looked up on a map first, so addresses need to be specific enough to find.

Event and day rules

The Calendar and Full-Screen Calendar modules share two small rules engines that change how the calendar looks without touching the events themselves. Both are off until you add a rule, and both are edited under the module's settings in the editor.

Event rules (eventRules) restyle or hide individual events. Each rule is a match plus the changes to apply:

FieldTypeDescription
idstringStable identifier for the rule
matchobjectWhat the rule applies to (see below)
hidebooleanDrop matching events from the view entirely
colorstringReplace the calendar's color for these events
opacitynumber0.1–1, multiplied with whatever fade the view already applies
iconstringAn emoji or short string shown in place of the color dot
titlestringReplace the displayed title

Day rules (dayRules) tint whole days and add badges to them, on the views that draw days as cells or columns:

FieldTypeDescription
idstringStable identifier for the rule
matchobjectWhich days the rule applies to (see below)
backgroundstringA color, or auto to tint the day from its own events' colors
backgroundImagestringA picture painted on the day, under its number and events: a built-in path such as /starter-day-art/birthday.svg, or the serve URL of a picture in the media library's calendar-art folder
backgroundDimnumber0–0.9, how far the picture fades; default 0.4
backgroundScalenumber10–100, picture size; 100 (the default) fills the day, smaller values span that percent of the day's longer side
backgroundPositionXnumber0–100, where the picture sits left to right when it is smaller than the day; 0 is the left edge, 100 the right, 50 (the default) centered
backgroundPositionYnumber0–100, where the picture sits top to bottom; 0 is the top edge, 100 the bottom, 50 (the default) centered
opacitynumber0.1–1, applied to the day
borderColorstringOutline color for the day
badgeIcon, badgeText, badgeColorstringA small marker drawn on the day

Specific days narrows a rule to fixed dates: a day of every month (payday on the 15th), a fixed date each year (October 31), every day of one month, the last day of the month (any month, or just one), or the nth weekday of the month, 1st through 5th or the last, so "the 4th Thursday of November" works. Days that don't exist in a month never match: the 31st simply skips shorter months. A rule's other choices (a badge, an outline, a background) then apply to exactly those days.

A day rule's background can also be a picture: pick from the art that ships with Home Screens (birthdays, Halloween, Christmas, and other quiet patterns) or add your own image or SVG under Your pictures. The picture is painted on the day cell exactly as it otherwise renders, above the cell's own fill and under the day's number and events, everywhere the calendar draws days. Art dimming fades the picture itself: transparent parts of a PNG leave the cell untouched, so the cell keeps its normal look with the art laid in. Picture size shrinks the picture inside the day (at 100 it fills the day as before), and Horizontal position and Vertical position choose which corner or edge a smaller picture sits against. An SVG you add needs a viewBox (or a fixed width and height) so it keeps its shape at every size; the library says so if one is missing.

Matching an event: every field you set has to hold (they combine with AND), and a rule with an empty match applies to everything:

FieldTypeDescription
textstringMatched against the title, case-insensitively
textMatchstringHow text is compared: contains (default), exact, or regex
sourceIdsarrayAny of these calendar sources (a Google calendar id, an iCal or iCloud source id, or holidays)
locationstringCase-insensitive substring of the event's location
allDaybooleanAll-day events only, or timed events only
pastbooleantrue = already finished, false = upcoming or running now
kindstringbirthday, holiday, or event

Matching a day uses the same idea:

FieldTypeDescription
whenstringtoday, past, or future
daysOfWeekarrayDay numbers where 0 is Sunday; empty or unset means every day
monthsarrayMonth numbers where 0 is January; empty or unset means every month. On its own it matches every day of those months
dayOfMonthnumber1 to 31. Months without that day never match; combine with months for a fixed date each year
lastDayOfMonthbooleanThe final day of the month, whatever its length
weekdayOfMonthobject{ "week": 1..5 or "last", "weekday": 0..6 }, so the last Friday is { "week": "last", "weekday": 5 }
withEventsstringany (at least one event), none (an empty day), or matching (has an event matching eventMatch)
eventMatchobjectAn event match, used when withEvents is matching

Rules run from the top of the list down, and the first rule to set a property wins for that property: so list order is priority, and a later rule can still fill in something an earlier one left alone.

Module Styling

Every module supports these style properties, configurable in the Property Panel, except the full-screen modules and Display Control, which paint their own look and have no Style section:

PropertyTypeDefaultDescription
opacitynumber1Module opacity (0–1)
borderRadiusnumber12Corner rounding in pixels
paddingnumber16Inner padding in pixels
backgroundColorstring"rgba(0, 0, 0, 0.4)"Background color
textColorstring"#ffffff"Text color
fontFamilystring"inter"Font id from the built-in font list: inter, roboto, poppins, system-ui, playfair, lora, dm-serif, georgia, jetbrains, mono, bebas, caveat, pacifico. Raw CSS font stacks saved by older versions still work
fontSizenumber16Text size in pixels: the size on most modules, the smallest size on the ones that fit their text to their box (clock, countdown, date, greeting, weather, news, quote, dad joke, word of the day, this day in history, affirmations, sticky note, to-do list, multi-month calendar). Not edited directly any more: the editor's Text size slider is a percent, and a module with only this value shows it as a percent of what it shows on its own
textScalenumber,Text size, a percent (10–450) of what the module shows on its own: the fitted size on the modules that fit their text to their box, the registry base fontSize everywhere else. Unset = the stored fontSize stands. Setting it in the editor resets fontSize to the base
fontWeightnumber,Forces every piece of the module's text to one weight (100–900). Unset = each module keeps its own designed weights. Not available for plugin modules
backdropBlurnumber12Backdrop blur in pixels
borderWidthnumber1Border width in pixels
borderColorstring"rgba(255, 255, 255, 0.15)"Border color
shadowSizenumber8Box shadow size in pixels

The Sticky Note paints its own paper and ink: its background is the module's noteColor setting and its text is always dark, so the editor does not offer backgroundColor or textColor for it.

These are the values a newly added module starts with. A few modules override some of them on add: the four full-screen modules plus Shape & Divider and Icon start transparent with no padding, blur, border, or shadow; Video and Web Embed start with no padding; and Multi-Month Calendar and Chore Chart start at a larger base font size.

Settings every module shares

Alongside the options above, every module on a screen carries four instance settings that decide whether it renders: an on/off switch, a day-and-time schedule, conditional visibility driven by live values published by add-ons, and a background-provider flag that keeps a module's data loop running while other screens are showing. See the Configuration reference for their exact shape, and the Editor guide for how to set them.

Previous
Configuration
Next
API