Family dashboard integration for Home Assistant. Consolidates calendar views, chore tracking, trash collection and notification reminders into a unified family dashboard with reusable Lovelace cards.
Screenshot is anonymized (PII removed) and the empty cells were demo-filled with Gemini Nano Banana so the layout reads at a glance.
My family is like most households: we struggle with the same small questions every single day. What’s happening this afternoon? What are we eating? Whose turn is it to take out the trash? When you factor in ADHD, these questions aren't just trivial—they are obstacles. For my family members, "out of sight" literally means "out of mind." Cluttered phone apps, hidden notifications, and fragmented calendars create a constant mental tax.
I built FamilyBoard together with my family to serve as an external brain for our home. Because we designed it as a team, every feature is tuned to how we actually live. It moves the "Status Update" fatigue away from shouting across the kitchen and into a calm, persistent display on the wall.
It is designed for:
- Visual Persistence: Keeping chores and events visible so they don't disappear from the mind (supporting object permanence).
- Predictability: Surfacing trash days and meal plans before the "what now?" panic sets in.
- Cognitive Ease: A zero-scroll, zero-tap interface that passes the "Glance Test"—if you can't see the answer while walking past the tablet with a laundry basket, the UI has failed.
FamilyBoard doesn't ask my family to change how they function; it changes the environment to better support how they think.
- Bring your own calendar and tasks. Put events in whatever
calendar app you already use (Google, iCloud, CalDAV) and chores in
whatever to-do list you already use (Google Tasks, Microsoft To Do, a
local HA
todo). Sync them into Home Assistant once — bidirectionally if you want — and FamilyBoard reads from there. No second place to manage anything. - One unified overview. Per-member calendars, shared family calendars, trash collection, chores and reminders are merged into a single screen. Filter on the fly: just one person, just today, just chores, hide reminders that are already shown elsewhere.
- Reminders live where you want them. Tasks can render inside the calendar grid as time-blocks, or outside it as a separate reminders list — toggleable per dashboard so you don't see the same item twice.
- Native HA only. No
input_*helpers, no custom storage backend. Everything is aselect/text/switch/datetimeentity with proper restore-state and config-flow support.
Home Assistant ships a CalDAV integration, but it converts VTODOs into
HA's simplified TodoItem — which has no concept of RRULE,
DTSTART, PRIORITY, PERCENT-COMPLETE, LOCATION, URL or
CATEGORIES. Those fields are silently stripped on read and
permanently lost on write.
The practical damage is worst for recurring tasks: when you
complete a weekly chore, HA marks the VTODO COMPLETED and the
recurrence is gone. Nextcloud doesn't re-create it server-side,
Tasks.org handles recurrence client-side only, and HA never wrote the
next occurrence. The task simply disappears.
FamilyBoard solves this by owning the CalDAV connection:
| HA built-in CalDAV | FamilyBoard CalDAV | |
|---|---|---|
| RRULE on read | stripped | preserved |
| Complete recurring task | marks COMPLETED → task gone | advances DUE to next occurrence |
| RRULE exhausted (COUNT/UNTIL) | n/a | marks COMPLETED with timestamp |
| DTSTART | stripped | preserved (anchors the RRULE) |
| PRIORITY | stripped | preserved (0–9) |
| PERCENT-COMPLETE | stripped | preserved (0–100) |
| LOCATION, URL | stripped | preserved |
| CATEGORIES | stripped | preserved |
| Extra fields exposed via | — | extra_state_attributes.vtodo_items |
The resulting todo.* entities are standard HA TodoListEntity
instances, so they work with todo.get_items, automations, and
FamilyBoard's own chores pipeline — mix and match with HA Local To-do,
Google Tasks, or any other todo integration.
Successful client-side recurring completions through FamilyBoard CalDAV also emit an HA event. FamilyBoard uses it to credit the completed occurrence even when the task stays visible with the same UID and a new due date. This requires both integrations to be updated; it does not provide completion events for actions performed in phone apps.
It ships as a separate integration so you can use it without FamilyBoard — and use FamilyBoard without it:
Add that URL as an Integration under HACS → Custom repositories,
then configure it via Settings → Devices & Services → Add Integration
→ FamilyBoard CalDAV. There is no import dependency between the two;
FamilyBoard just reads the todo.* entities over the standard HA todo
platform.
- Per-member calendar proxies — primary + extra calendars, Google Tasks filtered out automatically.
- Cross-member "Alles" calendar — deduplicated event stream with multi-member markers (one event, multiple colored borders).
- Trash collection calendar — surfaces configured
sensor.*collection dates as all-day events, optionally with auto-generated chores. - Chores sensor — combined per-member list of
todo.*items, sorted overdue → upcoming → no-date, optionally cross-matched with calendar tasks for start/end times. - Urgency styling — overdue (red), due-soon (orange) and due-today (blue) chore rows are highlighted with a tinted background and colored border. Each tier can be toggled off or recolored via the Display sub-item.
- Per-member progress sensor — daily completion tracking with color rings. Full-screen confetti celebration on 100 % completion.
- Interactive snooze reminders — actionable mobile_app notifications scheduled at task start time, with persistence across HA restarts and away-aware delivery.
- Custom Lovelace cards — composable building blocks:
chores,calendar,filter,progress,countdown,recent-chores. Each takes its own config; users can mix them into any dashboard. - Tap-to-claim shared chores — claim a shared chore from the chores card or via the
familyboard.claim_choreservice; only the claimer is credited on completion. - Chore-completion history (energy-dashboard pattern) — per-member
total_increasingcounters (sensor.familyboard_completions_total_<member>, unittasks) feed into HA's recorder/statistics so the stockstatistics-graphcard produces hourly/daily/weekly/monthly chore charts. A bounded recent log (sensor.familyboard_recent_chores) drives the newcustom:familyboard-recent-chores-card. - Calendar category filter — tag each calendar with a category (
personal,work,school,hobby,family,shared,other); the dashboard renders one toggle chip per category in use, so you can hide the work calendar with one tap. Toggle state survives restarts. - Add-event form entities — built-in
select,text,switchanddatetimeentities power a "create event" form with cascading member → calendar pickers. - Event countdown — kiosk-editable countdown to a single target date (label + date), rendered by
custom:familyboard-countdown-card. Auto-hides when no label is set and self-clears the day after the event. - CalDAV connection (separate integration:
familyboard_caldav) — connect directly to a CalDAV server (Nextcloud, Baikal, iCloud, …) with full RFC 5545 VTODO support. Install it alongside FamilyBoard; thetodo.*entities it creates work inchores:/shared_chores:like any other todo entity. - Parcel bridge (separate integration:
parcel) — turns tracked shipments into things the board already understands: a pickup chore when a parcel is ready for collection, and a calendar event for the delivery window (or an all-day event when only the date is known). Pickup chores auto-complete once the shipment is delivered.
Click the badge at the top of this page, or follow the manual steps:
- In HACS, choose Integrations → ⋮ → Custom repositories and add
https://github.com/apiest/ha-familyboardas an Integration. - Search for FamilyBoard in HACS and install.
- Restart Home Assistant.
- Go to Settings → Devices & Services → Add Integration → FamilyBoard and configure members, trash and shared calendars/chores via the UI.
- Copy
custom_components/familyboard/into your HA config dir. - Restart Home Assistant.
- Add the integration via Settings → Devices & Services.
The integration registers its Lovelace card resources via the Lovelace resources API — no manual URL bookkeeping required.
YAML configuration is still supported as a bootstrap: any familyboard:
block in configuration.yaml is imported into the integration on first
start and upserted into sub-items on every subsequent restart.
Sub-items you added via the UI without a YAML twin are preserved.
FamilyBoard is configured entirely through the integration page:
Settings → Devices & Services → FamilyBoard → click the ➕ in the Sub-items section.
Each member, extra calendar, shared calendar, shared chore, trash sensor and the meal planner is its own sub-item (HA subentry). Add or remove them individually from that page; each appears as a separate row with edit / delete controls.
Available sub-item types:
| Sub-item | Cardinality | Description |
|---|---|---|
| Member | 0..N | A person — primary calendar, color, optional person/notify, chore lists. |
| Extra calendar | 0..N (linked to a member) | Additional calendar for an existing member. |
| Shared calendar | 0..N | A calendar shared by multiple members. |
| Shared chore | 0..N | A todo list shared by multiple members. |
| Trash collection | 0..N (one per type) | A sensor.* with the next collection date as state. |
| Meal planner | 0..1 | Singleton — meal calendar + AI suggestion settings. |
| Meal weekday override | 0..7 (one per weekday) | Tweak the AI meal prompt for one specific weekday (e.g. "Thursday: training at 6pm — keep it quick"). Optionally overrides the planner's default max prep time for that day. |
| Display | 0..1 | Singleton — toggle urgency tiers (due today / due soon / overdue) on or off and customise their accent colors. |
| Parcel bridge | 0..1 | Singleton — target todo list + calendar for parcel pickup chores and delivery events. Requires the separate parcel integration. |
The picker hides Meal planner once one exists and Meal weekday override once all seven weekdays are covered.
Trash auto-chores are now opt-in for new entries. When you add a trash sub-item via the UI, both empty bins and kliko at the curb reminder chores default to off. Tick the boxes you want created. Existing YAML / migrated v1 entries keep the legacy default-on behaviour.
YAML is still imported on every HA start as a bootstrap; each item is upserted into the matching sub-item by stable identity (member name, calendar entity, trash type, …). Sub-items added via the UI without a YAML twin are preserved across re-imports. Removing an item from YAML does not auto-delete the matching sub-item — clean up via the UI.
familyboard:
members:
- name: Person_1
color: "#4A90D9"
calendar: calendar.person_1
calendar_label: Personal
calendar_default_summary: ""
calendar_default_description: ""
person: person.person_1
notify: mobile_app_person_1
chores:
- todo.person_1
- todo.person_1_tasks
extra_calendars:
- entity: calendar.person_1_work
label: Work
default_summary: ""
default_description: ""
- name: Person_2
color: "#27AE60"
calendar: calendar.person_2
person: person.person_2
notify: mobile_app_person_2
chores:
- todo.person_2
trash:
- type: rest
sensor: sensor.trash_rest
label: Restafval
color: "#555555"
emoji: "🗑️"
time_bins: "21:00" # due time for bins chore (default 21:00)
time_kliko: "07:00" # due time for kliko chore (default 07:00)
- type: gft
sensor: sensor.trash_gft
shared_calendars:
- entity: calendar.shared
members: [Person_1, Person_2]
name: Shared
color: "#9B59B6"
shared_chores:
- entity: todo.trash
members: [Person_1, Person_2]
type: trash
name: Trash
- entity: todo.groceries
members: [Person_1, Person_2]
name: Groceries
meals:
calendar: calendar.meals
ai_task_entity: ai_task.gpt_oss_20b # required for suggest_meal
shopping_list: todo.groceries # optional; ingredients land here on accept
cuisines: [Nederlands, Italiaans, Mexicaans, Aziatisch, Mediterraans]
pantry_staples: [zout, peper, olie, boter, ui, knoflook, kruiden,
melk, eieren, rijst, pasta, sojasaus, ketjap,
tomatenblik, bouillonblokjes]
restrictions:
- "Geen paprika"
- "Geen vis"
max_minutes: 30
day_overrides:
thursday:
note: "Training om 18:00 — kies iets heel makkelijks"
max_minutes: 15
extra_notes: ""
caldav:
- url: https://nextcloud.local/remote.php/dav
username: familyboard
password: !secret caldav_password
name: Nextcloud
verify_ssl: true
display:
due_today_enabled: true
due_today_color: "#3498DB"
due_soon_enabled: true
due_soon_color: "#E67E22"
overdue_enabled: true
overdue_color: "#E74C3C"| Key | Required | Default | Description |
|---|---|---|---|
name |
yes | — | Display name |
calendar |
yes | — | Primary calendar entity_id |
calendar_label |
no | <name> privé |
Label shown in calendar picker |
calendar_default_summary |
no | — | Fallback summary for events without one |
calendar_default_description |
no | — | Fallback description for events without one |
color |
no | #4A90D9 |
Member color (hex). See Recommended palette below. |
person |
no | — | person.* entity for presence + avatar |
notify |
no | — | mobile_app_* notify target for reminders |
chores |
no | [] |
List of todo.* entity_ids |
extra_calendars |
no | [] |
Additional calendars (see below) |
category |
no | personal |
Calendar category for the filter chips. One of personal, work, school, hobby, family, shared, other. |
The dashboard auto-picks dark or light text per event, so any color works, but a softer pastel palette is friendlier on a wall-mounted tablet. All three pass WCAG AA contrast against the auto-picked dark text:
| Member | Hex |
|---|---|
| Blue | #A8C8EC |
| Green | #B5E0C2 |
| Pink | #F4C2D7 |
If you prefer the original saturated palette (#4A90D9, #27AE60,
#F39C12, …) just leave color: as-is — text will stay white on those.
| Key | Required | Default | Description |
|---|---|---|---|
entity |
yes | — | Calendar entity_id |
label |
yes | — | Display label in pickers |
default_summary |
no | — | Fallback summary |
default_description |
no | — | Fallback description |
category |
no | parent member's category | Calendar category for the filter chips (see Member options). |
| Key | Required | Default | Description |
|---|---|---|---|
type |
yes | — | Trash type identifier (rest, paper, gft, pmd, …) |
sensor |
yes | — | Sensor entity with the next collection date as state |
label |
no | from sensor | Display label |
color |
no | #B8B8B8 |
Color (hex) |
emoji |
no | per-type default | Emoji prefix |
reminder_bins |
no | true (YAML) / false (UI) |
When false, skip the auto-created "prullenbakken legen" chore (evening before collection). UI-added trash items default to false; YAML keeps the legacy default-on behaviour. |
reminder_kliko |
no | true (YAML) / false (UI) |
When false, skip the auto-created "kliko aan de weg" chore (morning of collection). UI-added trash items default to false; YAML keeps the legacy default-on behaviour. |
| Key | Required | Default | Description |
|---|---|---|---|
entity |
yes | — | Calendar entity_id |
members |
yes | — | List of member names |
name |
no | — | Display name |
color |
no | — | Color (hex) |
category |
no | shared |
Calendar category for the filter chips (see Member options). |
| Key | Required | Default | Description |
|---|---|---|---|
entity |
yes | — | todo.* entity_id |
members |
yes | — | List of member names |
type |
no | — | trash enables auto-creation from configured trash sensors |
name |
no | — | Display name |
color |
no | — | Color (hex) |
Drives the AI dinner-suggestion service
(familyboard.suggest_meal) and the meal calendar. All keys except
ai_task_entity are optional; defaults are baked in.
| Key | Required | Default | Description |
|---|---|---|---|
calendar |
no | — | calendar.* entity that holds the meal events |
ai_task_entity |
yes | — | ai_task.* entity that backs ai_task.generate_data |
shopping_list |
no | — | todo.* entity ingredients are appended to on accept |
cuisines |
no | NL/IT/MX/Asian/Med/ME | List of cuisines for variation hints. User list replaces the default fully when set. |
pantry_staples |
no | sensible NL kitchen list | Items the model should NOT add to the shopping list. User list replaces the default fully when set. |
restrictions |
no | [] |
Hard rules ("Geen paprika", "Geen vis", …) |
max_minutes |
no | 30 |
Maximum total prep time hint |
day_overrides |
no | {} |
Per-weekday tweaks. Keys are lowercase English weekday names. Each entry may set note and/or max_minutes. |
extra_notes |
no | "" |
Free-form text appended at the end of the prompt |
Deprecated: the legacy top-level
meal_calendar:andmeal_planner:keys are still accepted but emit a deprecation warning. Migrate to a singlemeals:block (withcalendar:nested inside).
Controls which urgency tiers are highlighted on the chores card and their accent colors. All tiers default to enabled when no Display sub-item exists.
| Key | Required | Default | Description |
|---|---|---|---|
due_today_enabled |
no | true |
Show blue highlight for chores due today |
due_today_color |
no | #3498DB |
Accent color for due-today tier |
due_soon_enabled |
no | true |
Show orange highlight for chores due within 2 days |
due_soon_color |
no | #E67E22 |
Accent color for due-soon tier |
overdue_enabled |
no | true |
Show red highlight for overdue chores |
overdue_color |
no | #E74C3C |
Accent color for overdue tier |
CalDAV support has been moved to a standalone integration:
FamilyBoard CalDAV
(familyboard_caldav). Install it alongside FamilyBoard and configure
each CalDAV server through Settings → Integrations → Add Integration →
FamilyBoard CalDAV. The todo.* entities it creates can be used in
FamilyBoard's chores: / shared_chores: like any other todo entity.
See Why FamilyBoard has its own CalDAV integration for the motivation.
Parcel tracking lives in its own integration too:
Install it, register a carrier provider (PostNL, DHL NL, …), then add the Parcel bridge sub-item here to wire it into the board:
| Key | Required | Description |
|---|---|---|
todo_entity |
yes | Todo list that receives parcel pickup chores. |
calendar_entity |
yes | Calendar that receives delivery events. |
With that in place FamilyBoard listens for parcel_event on the HA
event bus and:
- creates a pickup chore when a shipment reaches
pickup_ready, and auto-completes it ondelivered/expired/returned; - creates a timed calendar event for an announced delivery window, or an all-day event when only an expected date is known — replacing the event if the window later shifts.
Items are deduplicated through persistent storage, so a restart or a
repeated event won't produce duplicates. This sub-item is UI-only —
there is no parcel: YAML block.
| Entity | Description |
|---|---|
calendar.familyboard_<name> |
Per-member proxy (Google Tasks filtered out) |
calendar.familyboard_alles |
Cross-member deduplicated view with member markers |
calendar.familyboard_trash |
Trash collection dates from configured sensors |
| Entity | Description |
|---|---|
todo.caldav_<connection>_<calendar> |
CalDAV-backed todo list (created by the separate familyboard_caldav integration). The entity is named after its device, CalDAV (<connection>), plus the calendar name — check Settings → Entities for the exact id. Full RFC 5545 VTODO support; extra_state_attributes.vtodo_items exposes all fields. |
| Entity | Description |
|---|---|
sensor.familyboard_chores |
Combined chore list (count + items attribute) |
sensor.familyboard_members |
Member metadata for cards |
sensor.familyboard_progress |
Per-member daily completion progress |
sensor.familyboard_compliment |
Time-of-day greeting |
sensor.familyboard_recent_chores |
Bounded log of the most recent chore completions (drives the recent-chores card) |
sensor.familyboard_completions_total_<member> |
Per-member cumulative chore counter (total_increasing, unit tasks) — feeds HA statistics |
sensor.familyboard_meals |
Tonight's meal + 7-day week strip (requires calendar in the Meal planner sub-item) |
sensor.familyboard_recent_meals |
Top recent meal titles scored by usage and recency for the quick picker |
sensor.familyboard_meal_suggestion |
Latest AI-generated dinner suggestion (state = title; attrs = date, reason, ingredients, generated_at) |
binary_sensor.familyboard_meals_unplanned |
on when any of the next 7 days has no meal entry; placeholders count as planned |
If you want a day to count as "planned" without specifying a real meal
(eating out, leftovers, skip), create the calendar event with one of
these titles (case-insensitive): -, --, ?, geen, none,
n/a. The board renders 🚫 for that day and the
binary_sensor.familyboard_meals_unplanned stays off.
automation:
- alias: "Maaltijden plannen reminder"
trigger:
- platform: time
at: "18:00:00"
condition:
- condition: state
entity_id: binary_sensor.familyboard_meals_unplanned
state: "on"
action:
- service: notify.mobile_app_phone
data:
title: "Plan de maaltijden"
message: >-
{{ state_attr('binary_sensor.familyboard_meals_unplanned',
'count') }} dagen zonder maaltijd — eerstvolgende:
{{ state_attr('binary_sensor.familyboard_meals_unplanned',
'next_unplanned') }}.| Entity | Description |
|---|---|
select.familyboard_calendar |
Member/Alles filter chip |
select.familyboard_view |
Time window. State values are the keys today, 2_days, 3_days, work_week, week, two_weeks, month; the UI shows translated labels (Vandaag, 2 Dagen, …). |
select.familyboard_layout |
Layout mode (list / agenda) |
select.familyboard_event_member |
Add-event: member picker |
select.familyboard_event_calendar |
Add-event: calendar picker (cascades from member) |
text.familyboard_event_title |
Add-event: title input |
switch.familyboard_event_all_day |
Add-event: all-day toggle |
switch.familyboard_show_reminders |
Show/hide reminder notifications globally |
switch.familyboard_category_<category> |
One toggle per calendar category in use (personal, work, …); created dynamically |
text.familyboard_countdown_label |
Countdown: event label (empty hides the countdown card) |
datetime.familyboard_countdown_date |
Countdown: target date |
datetime.familyboard_event_start |
Add-event: start datetime |
datetime.familyboard_event_end |
Add-event: end datetime |
datetime.familyboard_day_start |
Add-event: all-day start |
datetime.familyboard_day_end |
Add-event: all-day end |
| Service | Description | Fields |
|---|---|---|
familyboard.add_event |
Create event from form entities | — (reads entity states) |
familyboard.add_meal |
Create an all-day meal event on the meal calendar | title, date (both optional; fall back to the form entities) |
familyboard.suggest_meal |
Generate a dinner suggestion via ai_task.generate_data and store it on sensor.familyboard_meal_suggestion |
date, ai_task_entity (both optional) |
familyboard.accept_meal_suggestion |
Apply the stored suggestion: create the meal event and append ingredients to the shopping list | — |
familyboard.clear_meal_suggestion |
Discard the current suggestion | — |
familyboard.claim_chore |
Assign a shared chore to a member, or release it with an empty member |
uid (required), member |
familyboard.snooze_test |
Test-fire a reminder | uid |
familyboard.cancel_reminder |
Cancel an active reminder | uid |
Each card is a self-contained building block — drop it in any view, any layout, alongside core or third-party cards.
| Card type | Required config | Description |
|---|---|---|
custom:familyboard-chores-card |
entity, filter_entity, view_entity, members_entity |
Sorted chore list with member filter |
custom:familyboard-calendar-card |
members_entity, calendar entity_ids |
Calendar timeline view |
custom:familyboard-filter-card |
filter_entity, members_entity |
Standalone member filter chips (alternative to the progress card's built-in filter) |
custom:familyboard-progress-card |
entity |
Per-member progress rings; with selectable: true + filter_entity the tiles double as the member filter |
custom:familyboard-recent-chores-card |
entity (default sensor.familyboard_recent_chores) |
Chronological list of the most recent chore completions with member-color dots |
custom:familyboard-countdown-card |
— (all optional) | Countdown to the target date in label_entity / date_entity. Kiosk-editable unless editable: false. |
custom:familyboard-view-card |
— (all optional) | Time-window chips for select.familyboard_view. Supports hidden_options / visible_options, extra_chips and an optional reminders toggle. |
custom:familyboard-meal-card |
— (all optional) | Tonight's meal + week strip from sensor.familyboard_meals, with the quick picker fed by sensor.familyboard_recent_meals. |
custom:familyboard-category-card |
— (all optional) | Calendar-category toggle chips, one per category in use. |
type: custom:familyboard-progress-card
entity: sensor.familyboard_progress
filter_entity: select.familyboard_calendar
selectable: trueWhen selectable: true and filter_entity is set, each tile becomes a
button that writes to the select entity. The selected member's tile gets
a colored back-glow; when the filter is Alles (or unavailable) every tile
glows. Clicking the sole-selected tile toggles back to Alles. Without
selectable / filter_entity the card is purely a display.
type: custom:familyboard-chores-card
entity: sensor.familyboard_chores
filter_entity: select.familyboard_calendar
view_entity: select.familyboard_view
members_entity: sensor.familyboard_members
# Optional:
# member: Person_1 # bind card to one member (or 'shared' for the algemene list)
# show_shared: false # hide shared chores from a personal/all view
# show_header: false # hide the member/shared headerSet member: shared to render only the shared ("algemene") chores; the
filter_entity member chips and the show_shared toggle are ignored in that
mode. The view filter (view_entity) still scopes the date window.
The calendar card can blend a full-color illustration into a timed event tile, picked from the title. Illustrations are inlined as SVG and each color role (accent, dark, skin, …) is painted through a CSS custom property, so the host page can re-theme them per tile, per member or via a HA theme without editing the SVGs.
Enable with event_images: true on the calendar card:
type: custom:familyboard-calendar-card
event_images: true
# … other optionsHow matching works:
- The title is lowercased, accents stripped, then split into tokens.
- A built-in NL + EN keyword map routes the first matching token to a
theme key. 29 themes ship out of the box:
badminton,bbq,beer,birthday,brain_chaos,buddies,camping,cleaning,doctor,family,fishing,food,friends,gym,hiking,movie,music,orderdelivery,outdoors,party,pet,phone,school,shopping,tennis,travel,walking,work,worktime. - The theme picks an SVG from
frontend/icons/events/<key>.svg. The SVG is sourced from unDraw and re-mapped so every fill resolves to a--fb-deco-*CSS variable. - No keyword match → no decoration. The tile renders plainly.
- Tile size decides the layout: ≥ 120 px tall gets a banner across the tile; 56–120 px gets a corner badge at bottom-right that scales with the tile (4:3, capped at 96×72); shorter or compact tiles stay plain.
- Reminders/chores skip the decoration entirely.
Themable color roles (defaults shown):
| Variable | Default | Used for |
|---|---|---|
--fb-deco-accent |
#2a9d8f |
primary accent (main object) |
--fb-deco-accent-2 |
#ffd166 |
secondary accent / highlight |
--fb-deco-dark |
#1d3557 |
silhouettes, clothing, outlines |
--fb-deco-grey |
#a8dadc |
neutral background shapes |
--fb-deco-skin |
#f6c8a8 |
skin tones |
--fb-deco-light |
#ffffff |
light highlights |
A few themes ship with per-theme overrides where the defaults
under-read (e.g. friends, beer, fishing). Override globally
from your HA theme:
familyboard:
card-mod-theme: familyboard
card-mod-root-yaml: |
.: |
familyboard-calendar-card { --fb-deco-accent: #ff0066; }Per-event override marker (anywhere in the description):
[FB:theme=<key>]— force a specific theme.[FB:theme=none]— suppress the decoration for one event even when a keyword would have matched.
To add a new theme, drop a themable SVG at
custom_components/familyboard/frontend/icons/events/<key>.svg (use
var(--fb-deco-*, fallback) for fills you want re-themable) and add
the keyword to event-themes.js.
There are two ways to use FamilyBoard in your dashboards:
- Compose your own — add the cards listed above into any dashboard, any view, any layout. The cards are independent; mix freely with core/HACS cards.
- Dashboard strategy —
strategy: type: custom:familyboardauto-generates a sections-view dashboard from the current members, chores and calendars sensors. Add or remove a member and the dashboard updates automatically. "Take Control" in the UI converts the generated layout back into editable YAML for further tweaking.
# A whole dashboard generated by the strategy:
strategy:
type: custom:familyboard
# All keys below are optional with sensible defaults
show_calendar: true
show_chores: true
show_progress: true
members_entity: sensor.familyboard_members
chores_entity: sensor.familyboard_chores
filter_entity: select.familyboard_calendar
view_entity: select.familyboard_viewYou can also use it as a view strategy (one view inside an existing dashboard):
views:
- strategy:
type: custom:familyboard
title: Family
path: familythemes/familyboard.yaml provides a dark Skylight-inspired theme that
the cards' default CSS variables target. Install by referencing the
themes/ folder from your configuration.yaml:
frontend:
themes: !include_dir_merge_named themesThen select FamilyBoard in your user profile theme picker. The theme is fully optional — the cards work with any theme.
The FamilyBoard cards themselves are self-contained, but the bundled
dashboard strategy (strategy: custom:familyboard) uses a few
third-party cards for chip styling and pop-ups. Install these from
HACS:
- Mushroom Cards
- card-mod
- Bubble Card — used for the Add event and Meal picker pop-ups.
- HA target: 2026.4.x (also works on 2025.1+).
- Single config entry; full UI options flow + YAML bootstrap.
- Local testing:
pip install -r requirements_test.txt && pytest. - CI: GitHub Actions runs hassfest, HACS validation and pytest on every push.
Run a real Home Assistant instance against this repo without touching your production HA.
Prerequisites: Docker, VS Code, and the Dev Containers extension.
- Open the repo in VS Code → Command Palette → Dev Containers:
Reopen in Container. First build runs
scripts/setup, which installsrequirements-dev.txt(Home Assistant + ruff + pytest stack). - In the integrated terminal:
scripts/develop. HA starts on http://localhost:8123 with this repo'scustom_components/familyboardonPYTHONPATH(no bind mounts or symlinks). VS Code users can also hit F5 → Home Assistant: dev (scripts/develop) to launch under debugpy. - First boot — exercise the real end-user flow:
- Create the owner account.
- Settings → Devices & services → Add integration and add:
- Local Calendar × 2 →
Dev A,Dev B - Local To-do × 3 →
Dev A,Dev B,Trash
- Local Calendar × 2 →
- Add FamilyBoard, then use the options flow to wire two
members (Dev_A, Dev_B) to the entities above and add
todo.trashas a shared chore (type: trash).
config/.storage/(git-ignored) persists this setup across container rebuilds, so it's a one-time exercise.
Iteration loop:
- Python edits → restart HA from Developer Tools → YAML → Restart
(or Ctrl+C in the
scripts/developterminal and re-run). - Frontend (
custom_components/familyboard/frontend/*.js) edits → hard-reload the browser (Ctrl+Shift+R). If a card "doesn't exist" after editing, open DevTools → Application → Service Workers → tick Bypass for network. - Format + lint:
scripts/lint. - Tests:
pytest.
Without Docker, the same scripts/setup and scripts/develop work in
a host virtualenv.
This project was developed with substantial help from AI coding assistants (GitHub Copilot / Claude). All code has been reviewed, tested against Home Assistant 2026.4.x and is maintained by a human — but if you spot a quirk that smells like an LLM hallucination, please open an issue.
Built-in event-decoration scenes are based on illustrations from unDraw (no attribution required by their license, but credit where credit is due).
FamilyBoard is a personal project I built for my own household and share in case others find it useful. Issues are triaged on a best-effort basis when I have time; there is no SLA and no guarantee of support. Pull requests with clear descriptions and tests are welcome.
For general Home Assistant questions, please use the community forum instead of the issue tracker.
MIT — see LICENSE.
