Software Engineer · Đà Nẵng
I build backend systems, developer tools, and things I want to exist.
Vietnamese input for macOS. A Unikey-style menu-bar app: type in every program without switching input sources.
Rust composes Telex and VNI, then restores English so text stays text, not tẽt. Swift injects per app — fast, paced in terminals, select-and-retype in Chromium — and ignores its own GVIT events.
Architecture
Pure composition in Rust (tone placement, syllable validation, fourteen TSV corpora) → C ABI with fixed-size buffers, no allocation on the hot path → Swift EventTapManager, TextInjector, and per-bundle app profiles. A watchdog polls tap health. The signing identity is pinned so Accessibility survives rebuilds. English words that are also valid Vietnamese syllables stay in known_limitations.tsv rather than being papered over. Not notarized yet; the DMG is signed with an Apple Development cert.
One content model, two languages. Nuxt reads; Django and PostgreSQL publish — an API boundary so the reading surface can move on its own.
Answers arrive as a stream. A per-thread SSE buffer renders each part as it lands; incomplete Markdown is a state to handle, not a bug.
The rules run without a screen. A headless simulation plays stages with bots before the Canvas art is allowed to change.
The rest of the ecosystem lives at kynguyen.cc.
Most of what I ship sits where backend correctness meets software people actually use: APIs that don't silently lie, migrations that don't surprise anyone on Friday, boundaries you can point to. I write the dull parts well — the rest gets easier.