An AI-powered daily dashboard for families, running on a Raspberry Pi.
Website: dinkydash.co
Every morning at 6am, DinkyDash calls the Claude API to generate a fresh, personalized dashboard β with calendar events, chore rotations, countdowns, fun facts, and daily challenges β then displays it on a small screen at home.
- AI-generated daily greeting and headline
- Person cards for each family member
- Chore rotation badges (automatically rotated daily)
- Countdowns to birthdays, holidays, and special dates
- Calendar events pulled from Google Calendar
- Fun facts, daily challenges, and a pet corner
[cron @ 6am] β generate.py β fetches Google Calendar
β builds prompt with family context
β calls Claude API
β saves dashboard_data.json
[browser] β app.py β reads dashboard_data.json
β renders dashboard on screen
- Python 3.11+
- An Anthropic API key
- A Google Calendar iCal URL (Google Calendar β Settings β Integrate calendar β Public address in iCal format)
git clone https://github.com/caspii/dinkydash.git
cd dinkydash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtcp config.example.yaml config.yamlEdit config.yaml with your family's details:
location: "Berlin, Germany"
calendar_url: "https://calendar.google.com/calendar/ical/your-email/basic.ics"
calendar_filter_emails:
- "spouse@example.com"
people:
- name: "Alice"
date_of_birth: "2015-03-15"
sex: "female"
image: "alice.jpg"
email: "alice@example.com"
interests: "drawing, dinosaurs"
- name: "Bob"
date_of_birth: "2017-06-20"
sex: "male"
image: "bob.jpg"
interests: "legos, soccer"
pets:
- name: "Buddy"
type: "dog"
image: "pet.jpg"
recurring:
- title: "Set Table"
emoji: "π½"
choices: ["Alice", "Bob"]
- title: "Feed Pet"
emoji: "π"
choices: ["Bob", "Alice"]
special_dates:
- title: "Christmas"
emoji: "π"
date: "12/25"
- title: "Summer Vacation"
emoji: "βοΈ"
date: "07/01"
claude_model: "claude-sonnet-4-5-20250929"
max_tokens: 2048
data_file: "dashboard_data.json"
anthropic_api_key_env: "ANTHROPIC_API_KEY"Create a .env file:
ANTHROPIC_API_KEY=sk-ant-...
Copy photos to the static/ directory. Filenames must match the image field in your config.
python generate.py # Generate today's dashboard
flask run --host=0.0.0.0 # Start the serverOpen http://localhost:5000 to see your dashboard. Use http://localhost:5000/preview for an 800x480 preview matching the Pi display.
| Field | Description |
|---|---|
location |
Your city/country, used for context in AI content |
calendar_url |
Google Calendar public iCal URL |
calendar_filter_emails |
Only show events where these emails are attendees |
people[] |
Family members: name, date_of_birth (YYYY-MM-DD), sex, image, email, interests |
pets[] |
Pets: name, type, image |
recurring[] |
Rotating chores: title, emoji, choices (list of names, rotated daily) |
special_dates[] |
Countdowns: title, emoji, date (MM/DD) |
claude_model |
Which Claude model to use |
max_tokens |
Max response length |
data_file |
Path for generated JSON (default: dashboard_data.json) |
anthropic_api_key_env |
Name of the env var holding your API key |
This section covers setting up DinkyDash on a Raspberry Pi with a small display so it runs as a permanent family dashboard.
- Raspberry Pi 4 (2GB+ RAM)
- MicroSD card (16GB+)
- DSI touchscreen display or HDMI monitor (800x480 recommended)
- Power supply
- Wi-Fi connection
Install Raspberry Pi OS (Debian Bookworm) using the Raspberry Pi Imager. Enable SSH and configure Wi-Fi during setup.
After first boot:
ssh pi@raspberrypi
sudo apt update && sudo apt upgrade -y
sudo apt install fonts-noto-color-emoji unclutter -yThe emoji font package is required for the dashboard to render emoji correctly.
ssh pi@raspberrypi
mkdir -p /home/pi/dinkydashFrom your local machine, copy the files:
rsync -az --exclude='venv' --exclude='.git' --exclude='__pycache__' \
./ pi@raspberrypi:/home/pi/dinkydash/Or use the deploy script:
./deploy_to_pi.shThen on the Pi:
cd /home/pi/dinkydash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtCreate the .env file on the Pi:
echo "ANTHROPIC_API_KEY=sk-ant-..." > /home/pi/dinkydash/.envTest it:
python generate.py
flask run --host=0.0.0.0Create /etc/systemd/system/dinkydash.service:
[Unit]
Description=DinkyDash Family Dashboard
After=network.target
[Service]
ExecStart=/home/pi/dinkydash/run_app.sh
User=pi
WorkingDirectory=/home/pi/dinkydash
Restart=always
[Install]
WantedBy=multi-user.targetCreate /home/pi/dinkydash/run_app.sh:
#!/bin/bash
cd /home/pi/dinkydash
source venv/bin/activate
export FLASK_APP=app.py
flask run --host=0.0.0.0Enable and start:
chmod +x /home/pi/dinkydash/run_app.sh
sudo systemctl daemon-reload
sudo systemctl enable dinkydash.service
sudo systemctl start dinkydash.servicecrontab -eAdd this line to generate a fresh dashboard every morning at 6am:
0 6 * * * cd /home/pi/dinkydash && source venv/bin/activate && python generate.py >> generate.log 2>&1This makes Chromium launch fullscreen on boot, showing the dashboard.
Create /home/pi/run.sh:
#!/bin/sh
# Wait for Flask to be ready (max 60 seconds)
echo 'Waiting for DinkyDash...'
i=0
while [ $i -lt 60 ]; do
if curl -s -o /dev/null -w '' http://localhost:5000/ 2>/dev/null; then
echo 'Ready!'
break
fi
i=$((i + 1))
sleep 1
done
/usr/bin/chromium-browser \
--kiosk \
--password-store=basic \
--disable-infobars \
--enable-features=OverlayScrollbar \
--disable-restore-session-state \
--noerrdialogs \
http://localhost:5000/chmod +x /home/pi/run.shEdit /home/pi/.config/lxsession/LXDE-pi/autostart:
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@unclutter
@xset s off
@xset -dpms
@xset s noblank
@/home/pi/run.sh
This disables the screensaver, hides the mouse cursor, and launches the dashboard in kiosk mode.
If your display is mounted upside down, add to /boot/firmware/config.txt:
[all]
lcd_rotate=2
display_rotate=2Note: On Bookworm, the boot config is at /boot/firmware/config.txt, not /boot/config.txt.
Save power by turning the display off at night.
Create /home/pi/screen_control.sh:
#!/bin/bash
if [ "$1" = "off" ]; then
vcgencmd display_power 0
elif [ "$1" = "on" ]; then
vcgencmd display_power 1
fichmod +x /home/pi/screen_control.shAdd to crontab:
0 22 * * * /home/pi/screen_control.sh off
0 7 * * * /home/pi/screen_control.sh on"localhost refused to connect" on boot β Race condition where Chromium starts before Flask is ready. The run.sh script above handles this by waiting up to 60 seconds.
GNOME Keyring password dialog β Chromium tries to use GNOME keyring on auto-login. The --password-store=basic flag prevents this.
Emoji not displaying β Install the emoji font: sudo apt install fonts-noto-color-emoji && fc-cache -fv
Wayland switch dialog on boot β Bookworm may prompt to switch from X11 to Wayland. Fix with: sudo raspi-config nonint do_wayland W1
Wi-Fi blocked β Fresh Bookworm installs may have Wi-Fi soft-blocked: sudo raspi-config nonint do_wifi_country DE && sudo rfkill unblock wifi
# Local development
source venv/bin/activate
python generate.py
flask run --host=0.0.0.0
# On the Pi
sudo systemctl status dinkydash # Check service
sudo systemctl restart dinkydash # Restart
journalctl -u dinkydash -f # View logs
/home/pi/screen_control.sh on # Screen on
/home/pi/screen_control.sh off # Screen off| File | Purpose |
|---|---|
generate.py |
Daily content generation (calendar, Claude API, JSON output) |
app.py |
Flask server that renders the dashboard |
config.yaml |
All configuration (people, calendar, chores, dates) |
config.example.yaml |
Template config to copy and customize |
templates/index.html |
Dashboard template (Bootstrap 5, optimized for 800x480) |
deploy_to_pi.sh |
Deployment script (rsync + service restart) |
.env |
API key (not in git) |
dashboard_data.json |
Generated daily content (not in git) |
MIT