Tzu Chi Weekly AI pipeline
Turns an edited Google Doc into a published weekly issue with Claude, audio and push
No public link. This page describes the problem, decisions and outcome.
At a glance
- Problem
- The Tzu Chi Foundation publishes a weekly newsletter.
- What I built
- An internal system that imports one issue end to end.
- Outcome
- Each weekly issue now goes out through it: the edited Google Doc becomes a published issue with audio and push.
- My role
- Solo
- Period
- 2026-01 → 2026-09
Abilities shown
Each links to the ability and its level on the Skills page.
- AI-native development Foundation
- Web Components Proven
- Backend services & APIs Proven
- Data pipelines & realtime Proven
- AI agents & tool use Proven
- Turning staff needs into tools Proven
- PostgreSQL & database testing In use
- Containers & self-hosting In use
- Security practice In use
- Speech (ASR & TTS) Built
The problem
The Tzu Chi Foundation publishes a weekly newsletter. Editors write each issue in Google Docs, and turning that into a digital edition meant copying articles by hand, swapping low-resolution images for originals, writing summaries, then building the e-book and notifying readers. Every issue repeated the same manual work.
What I built
An internal system that imports one issue end to end. A Fastify worker runs the pipeline, a Lit dashboard shows progress and lets editors review and publish, and a self-hosted Supabase stack behind a single Kong gateway holds the data, files and realtime channel. Claude, through the Claude Agent SDK, parses the issue, rewrites each article for the digital edition and writes its SEO description. The system also generates audio for each article, serves PDF e-books through its own flip-book reader (PDF.js with a forked StPageFlip) and sends push notifications to the reader app.
How it works
- The worker exports the Google Doc to Markdown and checks every image code against the high-resolution files in Drive.
- Images are compressed, stored, then replaced by the Drive originals under the same stable key.
- Claude parses the issue into structured articles, choosing only from 8 fixed categories.
- Each article is rewritten for digital reading and given a description; a pure-code pass converts Chinese numerals in dates and quantities to Arabic digits.
- Original and digital versions are stored side by side, then text-to-speech audio is generated per article.
- Every step and every Claude token is broadcast over Supabase Realtime, so editors watch the import live.
Decisions
- Filenames instead of Vision for image matching. Claude Vision matched images first, then a prefix join with Vision fallback. Both still misplaced photos, so the final design bakes a
category-article-imagecode into filenames and aborts the import with a per-image error when Doc and Drive disagree. - Named skills, not inline prompts. Parse, rewrite and describe each became a
SKILL.mdloaded as a system prompt, so one step can be debugged or changed alone. - Two timeout budgets and no tools. A single 2-minute idle timeout killed slow but healthy Opus parses. It became a 10-minute first-token budget plus a 2-minute idle limit, with streamed thinking and all tools disabled, which stopped parses from hitting the turn limit.
- Numbers normalised in code, not by the model. A conservative allowlist with tests keeps the conversion predictable.
Outcome
In use for the weekly newsletter. Built solo from January to September 2026, with a written security audit against ISO 27001 and OWASP. Built with Claude Code using a spec, plan, implement and review loop; 22 specs and plans live in the repo.