Phrase Passport: the travel guide I built for Seoul
A language and cultural field guide I can take on a trip, with phrases, pronunciation audio, and saved offline content.

I built Phrase Passport for trips where I wanted phrases, pronunciation audio and enough cultural context to know when to use them. I used it in Seoul, with guide material saved on my device for the times a connection wasn’t reliable. The guide also includes destination information and references, so I can return to the same material without starting another research session.
Starting with a destination
Research agents gather practical destination information and useful phrases, with references; text-to-speech adds pronunciation audio. The material becomes a saved guide for that destination, so I can find a phrase again without asking the model to reconstruct it.
The Seoul guide shows how those pieces come together. The screenshot above is from the Tokyo guide; it shows the same approach to phrases, culture, essentials, and sources.
The application around the AI
The version behind this story uses Next.js 16, React 19, TypeScript, and Tailwind CSS 4. The research workflow uses the OpenAI Responses API and multiple research-agent steps, with text-to-speech for selected phrases.
Those model calls are one part of the application. PostgreSQL, accessed through Drizzle ORM, stores the structured guide data. The web application and database run on Render. Generated audio lives in Cloudflare R2 and is delivered through a public CDN.
Readers can reopen the text and references and load saved audio without repeating the model calls that produced the guide.
Keeping audio links useful
Pronunciation adds another thing to store and retrieve. The audio is written to a private R2 bucket through its S3-compatible API, then served through the CDN. The bucket and the public delivery URL have different jobs: one stores the file, the other is how the browser receives it.
The implementation uses immutable cache headers for audio assets. It also retains redirects from the older /media/audio/[contentHash] route, so previously saved audio links can still reach the file after the delivery path changes.
What I can take offline
Phrase Passport is a progressive web app. A service worker, the Cache API, and IndexedDB work together to save selected guide content and audio on the device.
Offline means material that has already been saved on that device. It doesn’t mean the research agents or speech generation run without a connection. A destination or audio file that hasn’t been saved may still need the network.
For a trip, I prepare the guide while connected, then return to the saved material when the connection is unreliable.
Sources are part of the guide
A reference gives me somewhere to look when I want to check a detail. It doesn’t guarantee that a phrase has been reviewed by a native speaker, that every local convention is covered, or that travel and safety information is current.
Phrase Passport is practical preparation, not comprehensive travel or safety advice. Important information still needs checking against current authoritative sources.
To see the version I took to Seoul, open the guide.
