VIBATHON DEMO
Visit Greater Palm Springs
๐ด BasecampPulse
Automated, department-aware weekly reporting for Basecamp โ turning a flat overdue list into an executive-ready digest.
Summary
What we built
This project builds an automated weekly reporting tool that connects to Visit Greater Palm Springs' Basecamp account via API, pulls all to-do data, and generates a clean, readable summary report organized by department. Managers receive a plain-language digest highlighting overdue items by aging bucket (7, 14, 30+ days), unassigned tasks, and missing due dates. This eliminates manual report-building and helps leadership spot bottlenecks before they escalate.
Problem
The blind spot
Basecamp's built-in reporting only shows a single undifferentiated list of all overdue to-dos across every project and department, forcing managers to either wade through a massive combined list or manually run person-by-person reports.
- No way to view overdue items by department
- No way to identify aging tasks at a glance
- Unassigned and undated to-dos stay hidden
- Hours of manual report-building every week
Solution
A lightweight Python automation
Authenticate with the Basecamp 3 API, fetch all to-dos across projects, enrich them with assignee and project/department metadata, then classify each item by overdue aging bucket. An AI layer reads the structured data and writes a plain-language executive summary. The report renders as a clean HTML digest โ delivered on a schedule or on-demand through a Streamlit dashboard managers can trigger and preview in the browser.
Output
What managers see
- Overdue breakdown by department and aging bucket (1โ7, 8โ14, 15โ30, 30+ days)
- Due-status view โ 3 due today, 8 due this week, 14 upcoming โ so nothing slips next
- Risk lists: unassigned, missing due dates, and critical 30+ day items with direct Basecamp links
- My To-Dos view โ each signed-in user sees their own tasks
- AI-written executive briefing + export to PDF / Excel / CSV
Dashboard
Six views, one click each
๐ Overview
Snapshot KPIs, due-status, and aging breakdown for the whole organization at a glance.
๐ต My To-Dos
Personalized โ the signed-in user sees only the tasks assigned to them.
๐ By Department
Every team expanded with task, project, list, due date, aging, owner, and a Basecamp link.
โ ๏ธ Risk Lists
Unassigned overdue and critical 30+ day items isolated for immediate escalation.
๐ Trends
Week-over-week snapshots track whether overdue work is improving or slipping.
๐๏ธ Monthly & Weekly
Period rollups with charts and a downloadable Excel workbook.
AI Briefing
From raw data to a manager's memo
Claude reads the structured to-do data and writes a plain-language executive briefing โ no chart-reading required. A live example from the current account:
- Situation overview: 65%+ of tracked to-dos overdue; heaviest backlogs in Corporate Communications, Comms-PR, and Destination Experiences.
- Urgent (30+ days): 21 items past a month โ the oldest 172, 165, and 158 days overdue.
- Top contributors flagged for 1:1s: Julie Sinclair (11), Rob Osterberg (8), Colleen (7).
- Recommended actions: assign the 6 unassigned tasks today and add due dates to the 2 undated items.
Implementation
How it works
- Authenticate โ OAuth2 with the Basecamp 3 API; token cached and auto-refreshed (volume-persisted on Railway).
- Fetch & classify โ pull every to-do, compute overdue status and aging buckets, flag unassigned / undated items.
- Enrich โ map each assignee to a department via a maintained people directory (14 teams & sub-teams).
- Summarize โ an AI layer drafts a plain-language executive briefing from the structured data.
- Deliver โ Streamlit dashboard with Google sign-in & email allowlist, deployed on Railway.
Tools Used
The stack
Python 3.13
Streamlit ยท dashboard & UI
Basecamp 3 API ยท data source
Anthropic Claude ยท AI summary
Authlib / OIDC ยท Google sign-in
pandas ยท data shaping
requests-oauthlib ยท OAuth2
PyYAML ยท dept config
Jinja2 + pdfkit ยท HTML/PDF reports
Railway ยท deploy & hosting
GitHub ยท source & CI
Secrets supplied per-environment; tokens persist on a Railway volume across restarts.