- Show 6 days in a 3x2 grid (3 columns, 2 rows) with info panel spanning the full right column - Day columns explicitly grid-placed to prevent auto-flow into panel column - Larger fonts throughout: event cards 14px, day number 26px, clock 52px Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Family Calendar Display
A smart display application for Raspberry Pi that shows a color-coded, week-view family calendar with live weather, styled after wall-mounted family calendar devices (e.g. Skylight).
Project created: February 14, 2026 UI redesigned: June 30, 2026 — switched from a scrolling event list over a photo background to a light-themed week grid with per-person event colors.
Features
- 📅 Week-View Calendar - Sunday–Saturday grid with a "Next Week" preview column, Prev/Next navigation
- 👨👩👧👦 Color-Coded Family Members - Events tagged
[Name]are shown in that person's color (see below) - 🔎 Filter by Person - Dropdown to show only one family member's events
- 🌤️ Weather - Current temperature and icon in the header (OpenWeatherMap)
- 🕐 Real-time Clock - Current time and date display
- 📌 Read-only by design - The "+" button is a visual affordance only; this app reads a public iCal feed and cannot write events back to Google Calendar. Add/edit events directly in Google Calendar.
The previous rotating-background-photo and dad-joke features were dropped in the redesign to match the cleaner device look. The
/api/backgroundand/api/jokeendpoints still exist server-side if you want to bring them back.
Family Member Colors
Prefix an event title in Google Calendar with [Name] (case-insensitive) and the app will strip the prefix and color the event card accordingly. Unprefixed events fall back to a neutral gray "Family" color.
| Name / alias | Color |
|---|---|
[Ludwig] or [Dad] |
Blue |
[Michelle] or [Mom] |
Pink |
[Jason] |
Green |
[Daniel] |
Yellow |
Example: an event titled [Daniel] Football Practice displays as Football Practice in Daniel's yellow card. Member names/aliases/colors are configured in config.py (FAMILY_MEMBERS).
Requirements
- Python 3.8+
- Raspberry Pi (tested on Pi 3/4) or any Linux system
- Google Calendar API credentials
- OpenWeatherMap API key (free tier)
Quick Start
1. Clone the Repository
git clone ssh://git@gitea.meyfamily.co.nz:2222/luddie/Calender.git
cd Calender
2. Install Dependencies
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
3. Configure Environment Variables
cp .env.example .env
Edit .env and add your API keys:
# Get your OpenWeatherMap API key from: https://openweathermap.org/api
OPENWEATHER_API_KEY=your_api_key_here
# Your Google Calendar ID (found in Google Calendar settings)
GOOGLE_CALENDAR_ID=your_calendar_id@group.calendar.google.com
# Generate a secret key for Flask
FLASK_SECRET_KEY=your_random_secret_key
4. Get OpenWeatherMap API Key
- Go to OpenWeatherMap
- Sign up for a free account
- Navigate to "API keys" section
- Copy your API key
- Add it to your
.envfile asOPENWEATHER_API_KEY
Find Your Location Coordinates:
- Go to LatLong.net
- Search for your city
- Copy the latitude and longitude values
- Add them to your
.envfile asWEATHER_LATandWEATHER_LON
5. Set Up Google Calendar
Option 1: Public iCal Feed (Easiest - No Authentication)
- Open Google Calendar
- Go to Settings (⚙️ gear icon)
- Select the calendar you want to display
- Scroll down to "Integrate calendar"
- Copy the "Public URL to this calendar" in iCal format
- The URL looks like:
https://calendar.google.com/calendar/ical/...@group.calendar.google.com/public/basic.ics
- The URL looks like:
- Add this URL to your
.envfile asGOOGLE_CALENDAR_ICAL_URL - Also copy the Calendar ID (looks like
abc123...@group.calendar.google.com) - Add it to your
.envfile asGOOGLE_CALENDAR_ID
Note: Your calendar must be set to "Public" for this method to work.
Option 2: Google Calendar API with Credentials (Advanced)
If you prefer to use private calendars with authentication:
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable the Google Calendar API
- Create credentials (Service Account)
- Download the credentials JSON file
- Save it as
credentials/google_calendar_credentials.json - Share your calendar with the service account email
6. Set Up Family Member Colors (optional)
Prefix event titles in your calendar with [Name] to color-code them per person — see Family Member Colors above. Edit FAMILY_MEMBERS in config.py to change names, aliases, or colors.
7. Run the Application
python app.py
Visit http://localhost:5000 in your browser.
Raspberry Pi Deployment
Auto-start Flask Application
Create a systemd service:
sudo nano /etc/systemd/system/calendar-display.service
Add the following content:
[Unit]
Description=Calendar Display Flask App
After=network.target
[Service]
User=pi
WorkingDirectory=/home/pi/Calender
ExecStart=/home/pi/Calender/venv/bin/python app.py
Restart=always
Environment="PATH=/home/pi/Calender/venv/bin"
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable calendar-display.service
sudo systemctl start calendar-display.service
Configure Chromium Kiosk Mode
The Pi uses labwc (Wayland). Create the autostart entry:
mkdir -p ~/.config/autostart
nano ~/.config/autostart/chromium-kiosk.desktop
Add the following:
[Desktop Entry]
Type=Application
Name=Chromium Kiosk
Exec=chromium-browser --ozone-platform=wayland --kiosk --noerrdialogs --incognito --disable-infobars --simulate-touch-screen --force-show-cursor http://localhost:5002
X-GNOME-Autostart-enabled=true
Reboot
sudo reboot
The display should now start automatically on boot!
Restarting Without Rebooting
A helper script is included to restart both the Flask service and the Chromium kiosk without rebooting:
bash ~/restart-calendar.sh
This will:
- Restart the
calendar-displaysystemd service - Kill and relaunch Chromium in the correct Wayland session
Configuration
Environment Variables (.env file)
Weather Settings:
OPENWEATHER_API_KEY- Your OpenWeatherMap API keyWEATHER_LOCATION- City name and country code (e.g., "London,UK")WEATHER_LAT- Latitude of your locationWEATHER_LON- Longitude of your location
Calendar Settings:
GOOGLE_CALENDAR_ID- Your calendar IDGOOGLE_CALENDAR_ICAL_URL- Public iCal feed URL (easiest method)CALENDAR_DAYS_AHEAD- Used only by the legacy events fetch; the week view always fetches two weeks at a time
Update Intervals (in seconds):
WEATHER_UPDATE_INTERVAL- Weather refresh interval (default: 900)CALENDAR_UPDATE_INTERVAL- Calendar refresh interval (default: 300)
Other:
FLASK_SECRET_KEY- Flask session secret key
JavaScript Configuration (static/js/app.js)
For more precise control over update intervals, edit the INTERVALS object:
const INTERVALS = {
TIME: 1000, // 1 second
WEATHER: 900000, // 15 minutes
CALENDAR: 300000 // 5 minutes
};
Project Structure
Calender/
├── app.py # Main Flask application
├── config.py # Configuration management
├── requirements.txt # Python dependencies
├── .env # Environment variables (create from .env.example)
├── .env.example # Environment template
├── static/
│ ├── css/style.css # Styling
│ ├── js/app.js # Frontend JavaScript
│ └── backgrounds/ # Background images directory
├── templates/
│ └── index.html # Main display template
└── credentials/
└── google_calendar_credentials.json # Google API credentials
API Endpoints
GET /- Main display pageGET /api/weather- Weather data (cached for 15 min)GET /api/calendar?start=YYYY-MM-DD- Sunday-starting week of events plus a "Next Week" preview, color-coded by family member (cached per-week for 5 min).startdefaults to the current week if omitted.GET /api/background- Random background image (no longer used by the UI, kept for future use)GET /api/joke- Dad joke (no longer used by the UI, kept for future use)
Troubleshooting
Weather not loading
- Check your OpenWeatherMap API key is valid
- Ensure you're not exceeding the free tier rate limits (60 calls/min)
Calendar not loading
- Verify the iCal URL in
.envis correct and the calendar is set to Public - Check the calendar ID is correct
Events showing the wrong color / "Family" instead of a person
- The event title must start with
[Name]exactly, e.g.[Daniel] Football Practice - Check
FAMILY_MEMBERSinconfig.pyfor the recognized aliases
Display not starting on boot
- Check systemd service status:
sudo systemctl status calendar-display.service - View logs:
sudo journalctl -u calendar-display.service -f
Contributing
Feel free to submit issues or pull requests!
License
MIT License - Feel free to use and modify for personal use.
Credits
Built with:
- Flask - Web framework
- OpenWeatherMap API - Weather data
- Google Calendar API - Calendar integration
- icanhazdadjoke - Dad jokes API