Finding the Right Words
While honing my French language skills, I realized I had no reliable way to know whether I was internalizing the correct sounds.
Existing tools didn't solve this — so I built one.
Cyllenius Reader transforms any article into a bilingual reading experience — French and English, paragraph by paragraph — with audio to train the ear.
Rhyme & Reason
While built for personal use, I approached the architecture with the same rigor I apply to enterprise consulting. A few of the decisions that reflect that
Server-Side Architecture
All translation happens server-side — every call to Claude and Gmail runs through authenticated serverless functions. Nothing is ever processed in the browser, and the serverless model means the app scales automatically with no infrastructure to maintain.
Performance & Cost Efficiency
Featured articles are bundled directly into the build at compile time. Translated articles are cached locally after processing and flagged so they're never translated twice. No cold-start API dependencies, no repeat calls, no duplicate costs — the experience is instant from the first load.
Built for Forward Compatibility
I chose EPUB as the delivery format with scaling and forward compatibility in mind. It's the open standard across every major e-reader — Kindle, Kobo, Nook, BOOX — and it preserves the bilingual formatting exactly, so the feature works regardless of what device you're reading on.
Security in Layers
Gmail connects via OAuth 2.0 so no credentials are stored in plain text. Every backend request is authenticated with a server-side secret, and the app sits behind an access gate — it's not publicly reachable. The Anthropic API has a spending cap to prevent runaway cost exposure, and the Gmail connection runs through a dedicated inbox completely separate from any personal account. Risk is contained by design.
Under the Hood
Cyllenius Reader
- Forward any article to the Gmail account
- Apply the
to-translatelabel to queue it - After processing, label swaps to
translated— never re-processed
- Always-available featured articles
- Survive the "Clear all" action
- Great for curated content you return to often
- Paste any English article for instant translation
- No Gmail account or labels required
- Calls
translate-textAPI directly - Ideal for portfolio demos
- Basic auth gate on all non-API routes
- Runs at the Vercel edge — before any function executes
- Credentials stored as Vercel environment variables
- Refresh-token flow — no user login required at runtime
- Token refreshed on each serverless function invocation
- Scoped to Gmail read + label modification only
- Frontend and backend share the same secret
- Injected into the frontend bundle at build time via Vercel env
- Validated on every serverless function call
- Fetches all emails labeled
to-translate - Sends each article to Claude paragraph-by-paragraph
- Forced
tool_choice+ XML delimiters for reliable pairing - Swaps label to
translatedon success - 300s Vercel Pro timeout for long articles
- Returns all emails labeled
queue - Queue articles are never deleted or re-labeled
- Merged with localStorage cache on the frontend
- Translates a single pasted text (Demo Mode)
- Same Claude pipeline — tool_choice + XML pairing
- No Gmail interaction — self-contained
- Exports a translated article to Kindle
- Formats bilingual content for e-reader display
- Lists all available translated articles
- Merges Gmail fetch results with localStorage cache
- Permanent queue articles always appear at the top
- French paragraph above, English below — per
ParagraphPair - Left accent bar visually ties each FR/EN pair together
- Immersive parallel reading for language acquisition
- Click speaker icon or French text to hear pronunciation
- Per-paragraph speed controls: 0.5×, 0.8×, 1.0×
- French locale voice — native accent playback
- Articles stored in
localStorageafter first fetch - Survive page refresh — no redundant API calls
- "Clear all" removes non-queue articles only

