sunyi
Sunyi — Indonesian for quiet. So is the editor.
What even is this?
Sunyi is a minimal personal blog with a writing experience that feels like a code editor: a live markdown pane powered by CodeMirror, instant preview, and nothing else on the screen fighting for your attention. No dashboards. No widgets. No "engagement." Just a cursor and a page.
And it's real — it's live in production, it publishes actual posts, and it's the thing I write in every day. Not a demo that dies on localhost:3000.

Why I built it
Let's be honest: I reinvented the wheel. There are plenty of writing tools out there that are more reliable than mine, and half of them are free.
So why bother? Because none of them are mine. I wanted a tool shaped around exactly how I work — my UI, my keybindings, my quirks — where publishing is a single click and nothing gets in the way. Sunyi solves my problems, not everyone's.
How it works
The flow is deliberately boring, and that's the point:
- I write in a dedicated headless CMS.
- The CMS syncs my notes to the Go backend, which owns the data.
- The backend exposes a public endpoint, so this very portfolio can pull in and render my writing with zero manual copy-paste.
Effortless sync, one source of truth.
What I learned
Coming from .NET, Go rewired how I think about errors. Go forces you to confront every failure at the point it can happen — which, in my code, is almost everything. It's tedious at first, but it gave me a sharper mental model that I now bring back to my .NET work: handle the error where it breaks, not three layers up.
SEO taught me to respect the humble slug. I went with immutable slugs on purpose. If a slug tracked the post title, bookmarking first-draft and later renaming it to first-draft-v2 would quietly 404 everyone who saved the link. I could do something like {uid}-{title} — where only the uid matters and the title stays cosmetic — but for a personal blog that's over-engineering. Maybe I'm just lazy. Either way, not worth it (yet).
Multi-level subdomains are a special kind of pain. I first tried to host the API at sunyi.api.terminalissue.com. For reasons I never fully diagnosed, the app just refused to connect. So with my finest 404-IQ debugging, I flattened it to sunyi-api.terminalissue.com and it worked instantly. Might be a skill issue. But if it works, it works.
Stack
- Frontend — Nuxt 4, TypeScript, CodeMirror 6
- Backend — Go,
chi,pgx, PostgreSQL - Rendering —
markdown-itfor live preview,goldmarkon publish - Infra — Docker Compose, Caddy