A "Spotify Wrapped"-style dashboard for your Litter-Robot, displaying your cat's litter box activity stats, weight trends, and visit patterns. Includes a web dashboard and TRMNL e-ink display layouts.
This project connects to the Litter-Robot API to fetch activity history and generates:
- A web-based dashboard with animated slides showing stats and charts
- TRMNL e-ink display layouts in multiple sizes for ambient monitoring
- Visit tracking: Daily visit counts, visits per day average, peak hours
- Weight monitoring: Average weight, min/max, trend detection (gaining/losing/stable)
- Timing analysis: Longest and shortest gaps between visits
- Personality traits: Fun categorizations like "Night Owl", "Early Bird", "Creature of Habit"
- Charts: Visual visit history and weight trends over time
The system uses a decoupled architecture separating data fetching from presentation:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ GitHub Actions │────▶│ Litter-Robot │────▶│ site/data.json│
│ (scheduled) │ │ API │ │ (committed) │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌────────────────────────────────┼────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Netlify │ │ TRMNL │ │ JSON Endpoint │
│ Web Dashboard │ │ E-ink Display │ │ (data feed) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Purpose: Automated data fetching on a schedule
- Schedule: Runs every 4 hours via cron (
0 */4 * * *) - Workflow:
.github/workflows/fetch-data.yml - Environment: Uses
litterbot-fetchenvironment for secrets - Process:
- Checks out repository
- Installs Python 3.13 and dependencies via
uv - Runs
fetch_data.pyto pull data from Litter-Robot API - Commits updated
site/data.jsonif changed - Triggers Netlify deploy via build hook
- Purpose: Hosts the static web dashboard
- Publish directory:
site/ - Features:
- Static file hosting for
index.htmland assets - Serves
data.jsonas a public JSON endpoint - Auto-deploys when triggered by GitHub Actions via build hook
- Static file hosting for
- Purpose: E-ink dashboard display for ambient monitoring
- Data source: Fetches JSON from the Netlify-hosted
data.jsonendpoint - Templating: Uses Liquid templating to render data
- Charts: Highcharts via TRMNL's CDN for visit and weight visualizations
litterbot-wrapped/
├── fetch_data.py # Data fetching and stats computation
├── site/
│ ├── index.html # Web dashboard (static HTML + JS)
│ ├── data.json # Generated stats (auto-updated)
│ └── icon.png # Site icon
├── trmnl/
│ ├── trmnl-full.html # Full-size TRMNL layout (800x480)
│ ├── trmnl-half-horizontal.html # Half-horizontal (800x240)
│ ├── trmnl-half-vertical.html # Half-vertical (400x480)
│ └── trmnl-quad.html # Quadrant size (400x240)
├── .github/
│ └── workflows/
│ └── fetch-data.yml # GitHub Actions workflow
├── pyproject.toml # Python dependencies
└── CLAUDE.md # Development instructions
- Python 3.13+
- uv package manager
- Litter-Robot account with connected device
- GitHub repository
- Netlify account (for web hosting)
- TRMNL device (optional, for e-ink display)
-
Clone the repository:
git clone https://github.com/yourusername/litterbot-wrapped.git cd litterbot-wrapped -
Install dependencies:
uv sync
-
Create a
.envfile with your credentials:LITTERBOT_USERNAME=your-email@example.com LITTERBOT_PASSWORD=your-password CAT_NAME=YourCatsName -
Fetch data locally:
uv run python fetch_data.py
-
Serve the site locally (optional):
cd site && python -m http.server 8000
-
Create a GitHub environment named
litterbot-fetch -
Add the following secrets to the environment:
LITTERBOT_USERNAME- Your Litter-Robot account emailLITTERBOT_PASSWORD- Your Litter-Robot account passwordCAT_NAME- Your cat's name (displayed on dashboard)NETLIFY_BUILD_HOOK- Netlify build hook URL for triggering deploys
-
The workflow will run automatically every 4 hours, or trigger manually via "Run workflow"
-
Connect your GitHub repository to Netlify
-
Configure build settings:
- Publish directory:
site - Build command: (none needed, static files only)
- Publish directory:
-
Create a build hook:
- Go to Site settings > Build & deploy > Build hooks
- Create a hook named "GitHub Actions trigger"
- Copy the URL and add it as the
NETLIFY_BUILD_HOOKsecret in GitHub
-
In the TRMNL app, create a new Private Plugin
-
Configure the plugin:
- Strategy: Polling
- Polling URL:
https://your-netlify-site.netlify.app/data.json - Polling Interval: 4 hours (to match GitHub Actions schedule)
-
Copy the appropriate layout HTML from
trmnl/based on your desired display size:trmnl-full.html- Full screen (800x480)trmnl-half-horizontal.html- Wide banner (800x240)trmnl-half-vertical.html- Tall sidebar (400x480)trmnl-quad.html- Quarter screen (400x240)
-
Paste the HTML into the plugin's markup editor
The data.json file contains:
{
"cat_name": "Saba",
"robot_name": "scoopy",
"generated_at": "2026-01-03T16:16:15.052321-08:00",
"date_range": {
"start": "Dec 27",
"end": "Jan 03, 2026",
"display": "Dec 27 - Jan 03, 2026"
},
"personality_traits": ["Early Bird", "Weekday Regular"],
"total_visits": 21,
"visits_per_day": 3.1,
"chart_data": [
{ "weekday": "Sat", "display": "12/27", "count": 1 }
],
"weight_history": [
{ "display": "12/27", "weight": 11.2 }
],
"timing": {
"longest_gap": "15h 56m",
"shortest_gap": "2h 19m"
},
"weight": {
"average": 11.3,
"min": 10.5,
"max": 12.3,
"trend": "gaining",
"change": 0.12
},
"peak_hour": {
"hour": 11,
"count": 3,
"display": "11:00 AM"
},
"robot_stats": {
"clean_cycles": 21,
"interruptions": 3
}
}- pylitterbot - Async Python library for Litter-Robot API
- python-dotenv - Environment variable management
MIT