Architecture
Five stages. Seven APIs. Zero manual steps.
The pipeline
Once a month, a GitHub Action scrapes Milan's cultural calendar via milanopocket.it and web sources, then feeds everything to Claude Sonnet which structures the events in Supabase Postgres. Every morning, Open-Meteo delivers the 3-day weather forecast.
Every morning generate_speech.py pulls the day's events and weather and feeds them to Claude Sonnet with a prompt tuned for a Luxottica audience aged 25–45. The model writes a 60–100 second briefing in ALMA's voice and saves it to Supabase.
generate_video.py chains four services: ElevenLabs converts the script to MP3 (voice Bianca) → Kling generates the talking-head avatar video → Whisper produces word-level subtitle timing → ffmpeg assembles intro, body, outro and burns the subtitles. The final MP4 is uploaded to Supabase Storage.
send_email.py uses Resend to deliver a branded HTML email from alma@alma-milano.com to 87 Performance Team members. One CTA button links to the video, one link to the archive on alma-milano.com. Done by 9 AM.
alma-milano.com is a static site built by Claude Sonnet, deployed on Vercel and connected to Supabase. It reads live data on every page load — no build step needed. The archive updates automatically as new videos are uploaded.
GitHub Actions workflows
-
monthly_dataset.ymlRuns on the 25th of each month — scrapes Milan events, populates the DB for the next month.
-
daily_concierge.ymlMon–Fri 09:00 CEST — fetches weather, calls Claude, writes today's speech to Supabase.
-
generate_video.ymlChained automatically after speech generation — runs the full TTS → Avatar → Whisper → ffmpeg pipeline (~20 min).
-
send_email.ymlChained automatically after video generation — sends today's briefing to all recipients via Resend (~10 seconds).
Tech stack