This site
Static, trilingual, self-hosted. No CMS, no database.
The problem
A portfolio and technical writing site. It has to be fast, indexable in three languages, and cheap to run indefinitely.
Architecture decisions
Static, not server-rendered.
Astro with output: 'static'. The build produces plain HTML. There’s no
runtime to break at 3am, no database to back up, no attack surface beyond
nginx.
Git as the CMS. Content is MDX files in the repo. Version history is free. And it means an agent can publish — an LLM can’t fill in a form, but it can write a file and commit it.
i18n with the infrastructure in place, not the content.
English at the root, /es/ and /pt/ for the UI. Every route carries
correct hreflang, including x-default. Posts can be translated one at a
time without a refactor — and untranslated ones simply don’t generate a
route, so hreflang never points at a page that doesn’t exist.
Self-hosted, not on a platform. Multi-stage Dockerfile — Node to build, nginx to serve. Deployed to my own VPS via Dokploy, with Cloudflare in front for TLS and caching.
The trade-off
Vercel would have been faster to set up and would have handled TLS for me. I spent an evening debugging an ACME certificate that failed because DNS hadn’t propagated when Traefik first tried to issue — and Traefik caches the failure without retrying.
That’s the cost of running your own infrastructure. It’s also the reason I know how it works.
Result
Live at leanalvarez.com. Static HTML, three languages, one Docker image.